2011-10-12 14 views
5

Bir XML dosyası okuyan kodum var. İhtiyacım olan öğelerin özelliklerinin bazıları isteğe bağlıdır. Onları yönetmek için Option [T] kullanmaya çalışıyorum. Scala'da isteğe bağlı xml öznitelikleri işleniyor

(node \ "@attr").textOption.getOrElse("Some default value") 

düğüm "attr" özniteliği varsa

, bu kodu: sonra

class NodeSeqWrapper(nodeSeq: NodeSeq) { 
    def textOption: Option[String] = { 
    val text = nodeSeq.text 
    if (text == null || text.length == 0) None else Some(text) 
    } 
} 
implicit def nodeSeqWrapper(nodeSeq: NodeSeq): NodeSeqWrapper = 
    new NodeSeqWrapper(nodeSeq) 

ve böyle diyoruz: Ben \ Düğüm operatör tarafından döndürülen NodeSeq tipini pezevenk için aşağıdaki yazdım değeri alır. Eğer değilse, "Bazı varsayılan değerler" değeri döndürülür.

Bunu nasıl geliştirebilirim? Sınıf tanımını örtülü yönteme katlamanın bir yolu var mı? "İsteğe bağlı" özellik değerlerini almanın daha iyi bir yolu var mı? Option[T] "doğru" kullanıyorum mı?

+0

"textOption" yönteminizi, "Seq" sinin "head" ve "headOption" yöntemleriyle aynı şekilde çağırmak isteyebilirsiniz. –

+0

Kulağa hoş geliyor. Kodumu değiştireceğim. Ayrıca soru güncelleniyor. – Ralph

cevap

4

Bunu çok deyimsel bir şekilde yaptığınızı söyleyebilirim, evet.

aşağıdaki gibi "tanımları kat" olabilir

:

implicit def enrichNodeSeq(nodeSeq: NodeSeq) = new AnyRef { 
    def textOption : Option[String] = { 
    val text = nodeSeq.text 
    if (text == null || text.length == 0) None else Some(text) 
    } 
} 

her zaman sonuca .getOrElse(...) başvuruyorsanız, ayrıca ikinci bir versiyonunu textOrElse(elze : String) : String tanımlamak isteyebilirsiniz:

implicit def enrichNodeSeq(nodeSeq: NodeSeq) = new AnyRef { 
    def textOption : Option[String] = { 
    val text = nodeSeq.text 
    if (text == null || text.length == 0) None else Some(text) 
    } 

    def textOrElse(elze : String) : String = textOption.getOrElse(elze) 
} 

O işleri biraz daha özlü hale getirecek.

scala> (<b>Hello</b> : NodeSeq).textOrElse("No text found.") 
resN: String = Hello 
scala> (<br /> : NodeSeq).textOrElse("No text found.") 
resM: String = No text found. 
+0

Aradığım şey bu. İlk denememde anonim bir sınıf kullanmayı denedim ('new {...}') ve işe yaramadı. Ayrıca textOrElse yöntemini de beğeniyorum. Teşekkürler. – Ralph

+2

"Tanımları katlama" seçeneğinin, ek yöntemlerinizi çağırdığınızda Java yansımasının kullanılmasına dikkat edin. Ekstra sınıfı bildirmek değil. –

+0

@ Jean-PhilippePellet İyi nokta! JVM JIT derleyicisinin, yöntemin adının statik bir dizge olarak verildiği durumlarda, yansıtıcı çağrılar işlemede oldukça iyi olduğundan şüphelenirim. – Philippe

2

Yanıt, Scala 2.10'dan beri örtük sınıfların tanıtımıyla geliştirilebilir.

http://docs.scala-lang.org/overviews/core/implicit-classes.html

op örtülü bir sınıfı şöyle kullanılarak yeniden yazılabilir verdi örnek:

: örneğin durumda sınıfları için kısıtlama bir çift izler

object SomeExtensions { 

    implicit class ExtendedNodeSeq(nodeSeq: NodeSeq) { 
    def textOption: Option[String] = { 
     val text = nodeSeq.text 
     if (text == null || text.length == 0) None else Some(text) 
    } 
    } 

} 

Not

  1. Başka bir özellik/sınıf/nesne içinde tanımlanmaları gerekir.
  2. Yapıcılarına yalnızca örtük olmayan bir bağımsız değişken alabilirler.