【问题标题】:How to use extractor in polymorphic unapply?如何在多态 unapply 中使用提取器?
【发布时间】:2013-04-12 11:02:24
【问题描述】:

我真的不明白这个小东西。我有一个抽象类 Box 有几个不同类型的子类。例如

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

Box 的伴生对象中的 apply 方法很简单:

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 有点麻烦。我的第一个想法是在类型上使用模式匹配,如下所示:

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

}

由于类型擦除,这根本不起作用。

第二次尝试是一个泛型 Box[T] 类型 T 和一个重新定义的抽象类型成员 在每个子类中。例如:

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

因此,我可以将我的 unapply 重写为:

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

不幸的是,这也不起作用。所以我猜是显式类型引用 in Box[String] 也被删除,所以我需要使用类型清单。 可能是这样的:

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

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

此代码编译(2.10),但仍然没有所需的隐式转换。 为什么?

简单的问题,有没有办法在不使用反射的情况下进行值提取 还是清单?

真正让我感到困惑的是,是否有一种简单(r)的组合方式 多态性和模式匹配?如果没有,Scala 中是否还有其他方法可以 达到类似的效果?

有什么想法或建议吗?

非常感谢。

【问题讨论】:

    标签: scala extractor unapply


    【解决方案1】:

    你可以试试这个.. :)

      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 !
    

    【讨论】:

    • 是的,就是这样。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2012-09-02
    • 2016-04-15
    • 1970-01-01
    • 2022-01-24
    • 1970-01-01
    • 2021-10-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多