2

给定一个多态性状

 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]]

我不确定这是最好的,甚至是“正确”的方法。感谢您的任何建议。

4

2 回答 2

5

正如@Kim Stebel 指出的那样,您在Transform[T]T并且必须是因为T同时出现在同位和反位中) 不是的子类型,也不能成为。def apply(t : T) : T)Transform[Nothing]Transform[String]

如果您主要关心的是每次调用 Kim 时的实例创建,def Id[A]那么您最好的模型是conformsPredef 中的 in 定义,

private[this] final val singleton_<:< = new <:<[Any,Any] { def apply(x: Any): Any = x }
implicit def conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A]

IE。使用多态方法,将单例值转换为适当的类型。这是擦除是一种胜利的场合之一。

应用于您的情况,我们将有,

object SingletonId extends Transform[Any] { def apply(t : Any) = t }
def Id[A] = SingletonId.asInstanceOf[Transform[A]]

示例 REPL 会话,

scala> Id("foo")
res0: java.lang.String = foo

scala> Id(23)
res1: Int = 23
于 2011-10-03T08:38:43.647 回答
4

由于类型参数TinTransform[T]是不变的,Transform[Nothing]不是 的子类型Transform[String],因此编译器会抱怨它。但是Nothing无论如何在这里使用都没有意义,因为永远不会有Nothing. 那么如何将一个传递给apply方法呢?您将需要再次投射。我能看到的唯一选择是:

scala> def Id[A] = new Transform[A] { override def apply(t:A) = t }
Id: [A]=> java.lang.Object with Transform[A]

scala> Id(4)
res0: Int = 4

scala> Id("")
res1: java.lang.String = ""
于 2011-10-03T06:16:04.617 回答