2013-04-19 1 views
5

Je ne comprends pas vraiment ce petit truc. J'ai une classe abstraite Box avec plusieurs sous-classes pour différents types. Par exempleComment utiliser extracteur polymorphe non applicable?

abstract class Box 
class StringBox(val sValue : String) extends Box 

L'appliquer la méthode dans l'objet compagnon pour Box est simple:

object Box{ 
    def apply(s: String) = new StringBox(s) 
    def apply(b: Boolean) = new BooleanBox(b) 
    def apply(d: Double) = new DoubleBox(d) 
} 

donc je peux écrire

val sb = Box("StringBox) 

D'accord, l'écriture fait unapply quelques problèmes. Ma première idée était d'utiliser la correspondance de motif sur le type, comme celui-ci:

def unapply(b: Box) = b match { 
    case sb: StringBox => Some(sb.sValue) 
    case bb: BooleanBox => Some(bb.bValue) 
    case db: DoubleBox => Some(db.dValue) 
    case _ => None 

}

Ce qui ne fonctionne tout simplement pas à cause de ratures de type.

La deuxième tentative était une boîte générique [T] de type T et un membre de type abstrait redéfini dans chaque sous-classe. Par exemple:

abstract class Box[T] {def value : T} 
class StringBox(val sValue : String) extends Box[String] { 
    override def value : String = sValue 
} 

Par conséquent, je peux écrire mon re unapply comme:

def unapply[T](b: Box[T]) = b match { 
    case sb: Box[String] => Some(sb.value) 
    case bb: Box[Boolean] => Some(bb.value) 
    case db: Box[Double] => Some(db.value) 
    case _ => None 

Malheureusement, cela ne fonctionne pas non plus. Donc, je suppose que la référence de type explicite dans Box [String] est également effacée, donc j'ai besoin d'utiliser un manifeste de type à la place. Peut-être quelque chose comme:

def unapply[T](b: Box[_])(implicit target: Manifest[T]): Option[T] = { 

    if(b.value == target) Some(b.value.asInstanceOf[T]) 
    else None 
} 

Cette compiles de code (2.10), mais ne fonctionne toujours pas la conversion implicite désirée. Pourquoi?

Question simple, existe-t-il un moyen de faire l'extraction de valeur sans utiliser la réflexion ou un manifeste? Ce qui me dépasse vraiment, c'est la question de savoir s'il existe une méthode simple (r) pour combiner le polymorphisme et la correspondance de formes? Sinon, y a-t-il d'autres moyens dans Scala à d'accomplir un effet similaire?

Une idée ou des suggestions?

Merci beaucoup.

Répondre

5

Prolly vous pouvez essayer .. :)

abstract class Box[T](val v: T) 

    object Box { 
    def apply(s: String) = new StringBox(s) 
    def apply(b: Boolean) = new BooleanBox(b) 
    def apply(d: Double) = new DoubleBox(d) 

    } 

    class StringBox(sValue: String) extends Box(sValue) 
    object StringBox { 
    def unapply(b: StringBox) = Some(b.v) 
    } 

    class BooleanBox(sValue: Boolean) extends Box(sValue) 
    object BooleanBox { 
    def unapply(b: BooleanBox) = Some(b.v) 
    } 

    class DoubleBox(sValue: Double) extends Box(sValue) 
    object DoubleBox { 
    def unapply(b: DoubleBox) = Some(b.v) 
    } 

Vous pouvez l'utiliser comme -

def useCase[T](box: Box[T]) = box match { 
    case StringBox("StringBoxxx") => "I found the StringBox!" 
    case StringBox(s) => "Some other StringBox" 
    case BooleanBox(b) => { 
      if (b) "Omg! its true BooleanBox !" 
      else "its false BooleanBox :(" 
      } 
    case DoubleBox(x) => { 
       if (x > 3.14) "DoubleBox greater than pie !" 
       else if (x == 3.14) "DoubleBox with a pie !" 
       else "DoubleBox less than a pie !" 
    } 
    case _ => "What is it yaa ?" 
    }            

    useCase(Box("StringBoxxx")) //> res0: String = I found the StringBox! 
    useCase(Box("Whatever !")) //> res1: String = Some other StringBox 
    useCase(Box(true))   //> res2: String = Omg! its true BooleanBox ! 
    useCase(Box(false))   //> res3: String = its false BooleanBox :(
    useCase(Box(4))    //> res4: String = DoubleBox greater than pie ! 
    useCase(Box(3.14))   //> res5: String = DoubleBox with a pie ! 
    useCase(Box(2))    //> res6: String = DoubleBox less than a pie ! 
+0

Oui, voilà. Je vous remercie. –

+0

Votre bienvenue .. :) – Shrey

Questions connexes