(注意:这个动机需要漫长而艰苦的解释;你可以在这个
Accord issue上找到全面的讨论.它可能不是解决这个问题的正确方法,但我认为这个问题本身很有趣.)
我正在寻找一种实现二元运算符的方式,使得行为取决于右侧操作数的类型:如果与左侧操作数相同,则表现出一种行为,否则不同的行为.举个例子:
implicit class Extend[T](lhs: T) { def testAgainst(rhs: T) = println("same type") def testAgainst[U](rhs: U) = println("different type") }
第一个重载比第二个更具体,所以你会期望调用如5 testAgainst 10来触发第一个重载,而5 testAgainst“abcd”将调用第二个重载.虽然这在理论上是有道理的,但是由于擦除的签名对于两个重载都是相同的,所以不会进行编译.
我设法解决这个问题,需要在第一个重载中添加一个类型参数,但这正是我想避免的.一个不同的解决方案是修改通用重载,以要求编译器的证据表明类型之间没有子类型关系(与…相反,不幸的是Scala库不提供).
虽然在Scala中编码子类型关系通常很容易,但我发现没有办法编码缺少这种关系.有没有办法要求,因为第二次重载在编译时成为一个候选人,所以T< U或T>:> U是真的吗
解决方法
如果要强制这两种类型在编译时严格不同,那么
this is the question就可以了.使用定义=!=的一个答案,我们可以想象出多种方法,如下所示:
implicit class Extend[T](lhs: T) { def testAgainst(rhs: T) = println("same type") def testAgainst[U](rhs: U)(implicit ev: T =!= U) = println("different type") }
import scala.reflect.runtime.universe._ implicit class Extend[T: TypeTag](lhs: T) { def testAgainst[U: TypeTag](rhs: U): Boolean = typeOf[T] =:= typeOf[U] }
你当然可以修改它来分支行为.
scala> 1 testAgainst 2 res98: Boolean = true scala> 1 testAgainst "a" res99: Boolean = false scala> List(1,2,3) testAgainst List(true,false) rES100: Boolean = false scala> List(1,2) testAgainst List.empty[Int] rES102: Boolean = true
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。