Gre*_*idt 2 polymorphism singleton scala nothing
给出了像多态的特征
trait Transform[T] { def apply( t: T ) : T }
Run Code Online (Sandbox Code Playgroud)
人们可能希望实现各种专门的实例,例如
case class Add[Double] extends Transform[Double] { def apply( t: Double ) ... }
case class Append[String] extends Transform[String] { def apply( t: String ) ... }
Run Code Online (Sandbox Code Playgroud)
现在,经常需要的变换也是身份变换.对于所有类型T,最好只使用一个单例实例,而不是为每个类型T专门设置标识.我的问题是:在Scala中实现此目的的最佳方法是什么?
这是我到目前为止所发现的:看看List [T]如何实现List.empty [T]和Nil,我尝试使用Nothing作为类型T.这似乎是有道理的,因为Nothing是所有其他类型的子类型:
object Identity extends Transform[Nothing] {
def apply( t: Nothing ) = t
}
Run Code Online (Sandbox Code Playgroud)
这似乎有效.但是,无论我在哪里,都希望按原样使用此实例,如下所示:
val array = Array[Transform[String]]( Transform.Identity )
Run Code Online (Sandbox Code Playgroud)
我得到编译器错误"类型不匹配;找到:Identity.type,required:Transform [String]".为了使用它,我必须明确地使用它:
... Identity.asInstanceOf[Transform[String]]
Run Code Online (Sandbox Code Playgroud)
我不确定这是最好还是"正确"的做法.谢谢你的建议.
正如@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]
Run Code Online (Sandbox Code Playgroud)
即.使用多态方法,将单个值转换为适当的类型.这是擦除胜利的场合之一.
应用于您的情况,我们会,
object SingletonId extends Transform[Any] { def apply(t : Any) = t }
def Id[A] = SingletonId.asInstanceOf[Transform[A]]
Run Code Online (Sandbox Code Playgroud)
示例REPL会话,
scala> Id("foo")
res0: java.lang.String = foo
scala> Id(23)
res1: Int = 23
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
385 次 |
| 最近记录: |