给定一个多态性状
trait Transform[T] { def apply( t: T ) : T }
人们可能喜欢实现各种专门的实例,例如
case class Add[Double] extends Transform[Double] { def apply( t: Double ) ... }
case class Append[String] extends Transform[String] { def apply( t: String ) ... }
等现在经常需要的变换也是恒等变换。与其为每种类型 T 专门化标识,不如为所有类型 T 使用一个单例实例似乎更可取。我的问题是:在 Scala 中实现这一点的最佳方法是什么?
这是我到目前为止的发现:查看 List[T] 如何实现 List.empty[T] 和 Nil,我尝试使用 Nothing 作为类型 T。这似乎是有道理的,因为 Nothing 是每个类型的子类型其他类型:
object Identity extends Transform[Nothing] {
def apply( t: Nothing ) = t
}
这似乎可行。然而,无论我想在哪里使用这个实例,就像这里一样:
val array = Array[Transform[String]]( Transform.Identity )
我收到编译器错误“类型不匹配;找到:Identity.type,需要:Transform[String]”。为了使用它,我必须显式地转换它:
... Identity.asInstanceOf[Transform[String]]
我不确定这是最好的,甚至是“正确”的方法。感谢您的任何建议。
最佳答案
正如@Kim Stebel 指出您的 Transform[T]
在 T
中不变(而且必须是因为 T
出现在 def apply(t : T) : T)
的同变体和反变体位置,所以 Transform[Nothing]
不是 Transform[String]
的子类型,不能成为。
如果您主要关心的是每次调用 Kim 的 def Id[A]
时创建的实例那么你最好的模型就是 conforms
的定义在预定义中,
private[this] final val singleton_<:< = new <:<[Any,Any] { def apply(x: Any): Any = x }
implicit def conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A]
即。使用多态方法,返回转换为适当类型的单例值。这是删除成功的场合之一。
应用于您的情况我们会,
object SingletonId extends Transform[Any] { def apply(t : Any) = t }
def Id[A] = SingletonId.asInstanceOf[Transform[A]]
示例 REPL session ,
scala> Id("foo")
res0: java.lang.String = foo
scala> Id(23)
res1: Int = 23
关于Scala:对多态类型的单例实例使用 Nothing,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7631478/