如何在多态 unapply 中使用提取器? [英] How to use extractor in polymorphic unapply?

查看:51
本文介绍了如何在多态 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆