基于Scala中的运行时类型信息进行区分

时间:2013-03-07 04:34:56

标签: scala

我想实现一个包含类型参数的子类,并根据参数是否符合参数来编写行为不同的函数实现。

考虑:

import scala.reflect.runtime.universe;

trait Lover {
    def love( amour : Any ) : String
}

class TypedLover[MY_TYPE]( implicit val myTypeTag : universe.TypeTag[MY_TYPE] ) extends Lover {
    def love( amour : Any ) : String =
        if ( ??? ) "You are totally my type." else "Nope, sorry, not my type."
}

我在这里有条件使用什么? [更新:如果函数参数 amour 符合MY_TYPE,则条件应返回true,否则返回false。]

非常感谢您的帮助。

4 个答案:

答案 0 :(得分:3)

class TypedLover[A](implicit tt: TypeTag[A]) extends Lover {
  def love(amour: Any) =
    if (tt.tpe =:= typeOf[String]) "You are totally my type."
    else "Nope, sorry, not my type."
}

scala> new TypedLover[String].love(null)
res2: String = You are totally my type.

scala> new TypedLover[Int].love(null)
res3: String = Nope, sorry, not my type.

有关TypeTag如何运作的详细介绍,请参阅此问题:Scala: What is a TypeTag and how do I use it?

答案 1 :(得分:2)

我想你想要这样的东西:

trait Lover {
  def love( amour : Any ) : String
}

class TypedLover[A : ClassTag] extends Lover {
    def love(amour : Any) = {
        if (implicitly[ClassTag[A]].runtimeClass == amour.getClass) {
                "Totally my type."
            } else {
                "Sorry, you are not my type."
            }
    }
}

val tl = new TypedLover[String]
tl.love(1) // res0: String = Sorry, you are not my type.
tl.love("Hello") //res1: String = Totally my type.

请注意,如果要捕获子类型,可以使用isAssignableFrom等方法代替==

答案 2 :(得分:0)

使用Manifest类,Scala可以解决类型擦除问题。指向用法的链接 - https://gist.github.com/anoopelias/4462155

答案 3 :(得分:0)

这是我能做的最好的事情。它不捕获真正的运行时类型信息,这是我想要的,但它至少在编译时捕获在使用点已知的类型信息:

import scala.reflect.runtime.universe._

trait Lover {
  def love[ T : TypeTag ]( amour : T ) : String;
}

class TypedLover[MY_TYPE : TypeTag] {
  def love[ T : TypeTag ]( amour : T ) : String =
    if ( implicitly[TypeTag[T]].tpe <:< implicitly[TypeTag[MY_TYPE]].tpe )
      "You are totally my type."
    else
      "Nope, sorry, not my type."
}

以下是它的工作原理:

scala> val intLover = new TypedLover[Int]
intLover: TypedLover[Int] = TypedLover@2d4cadc4

scala> intLover.love(7)
res2: String = You are totally my type.

scala> intLover.love("Hello")
res3: String = Nope, sorry, not my type.

scala> val stringLover = new TypedLover[String]
stringLover: TypedLover[String] = TypedLover@1f7c9157

scala> stringLover.love(7)
res4: String = Nope, sorry, not my type.

scala> stringLover.love("Hello")
res5: String = You are totally my type.

但是这里仍然无法捕获实际的运行时类型信息:

scala> val stringInAnyRef : Any = "Hello"
stringInAnyRef: Any = Hello

scala> stringLover.love( stringInAnyRef )
res7: String = Nope, sorry, not my type.

这不是完美的,但它是迄今为止我所做的最好的。