如何在多态 unapply 中使用提取器? [英] How to use extractor in polymorphic unapply?
问题描述
我真的不明白这个小东西.我有一个抽象类 Box有几个不同类型的子类.例如
I don't really get this little thingy. I have an abstract class Box with several sub-classes for different types. For example
abstract class Box
class StringBox(val sValue : String) extends Box
Box 伴随对象中的 apply 方法很简单:
The apply method in the companion object for Box is simple:
object Box{
def apply(s: String) = new StringBox(s)
def apply(b: Boolean) = new BooleanBox(b)
def apply(d: Double) = new DoubleBox(d)
}
所以我可以写
val sb = Box("StringBox)
好吧,写 unapply 有点麻烦.我的第一个想法是在类型上使用模式匹配,就像这样:
Okay, writing unapply makes some trouble. My first idea was to use pattern matching on the type, like this this:
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
}
由于类型擦除,这根本不起作用.
Which simply doesn't work because of type erasures.
第二次尝试是一个泛型 Box[T] 具有类型 T 和重新定义的抽象类型成员在每个子类中.例如:
Second attempt was a generic Box[T] with type T and an abstract type member re-defined in each sub classes. For instance:
abstract class Box[T] {def value : T}
class StringBox(val sValue : String) extends Box[String] {
override def value : String = sValue
}
因此,我可以将我的不申请重新写为:
Consequently, I can re write my unapply as:
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
不幸的是,这也不起作用.所以我猜是显式类型引用在 Box[String] 中也被删除,所以我需要改用类型清单.也许是这样的:
Unfortunately, this doesn't work either. So I guess the explicit type reference in Box[String] gets erased as well so I need to use a type manifest instead. Maybe something like:
def unapply[T](b: Box[_])(implicit target: Manifest[T]): Option[T] = {
if(b.value == target) Some(b.value.asInstanceOf[T])
else None
}
此代码编译(2.10)但仍然没有所需的隐式转换.为什么?
This code compiles (2.10) but still does not the desired implicit conversion. Why?
简单的问题,有没有不使用反射进行取值的方法还是清单?
Simple question, is there a way to do value extraction without using reflection or a manifest?
真正让我感到困惑的是,是否有一种简单的(r)方式来组合多态和模式匹配?如果没有,Scala 中是否还有其他方法可以达到类似的效果?
What really boggles me is the question if there is a simple(r) way to combine polymorphism and pattern matching? If not, are there other ways in Scala to accomplish a similar effect?
有什么想法或建议吗?
非常感谢.
推荐答案
你可以试试这个.. :)
Prolly you can try this.. :)
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)
}
您可以将其用作 --
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 !
这篇关于如何在多态 unapply 中使用提取器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!