我正在尝试创建一个与任何类型的引用相等匹配的方法,包括基元。怎么做到最好?
eq
仅在AnyRef
上定义。如果我们尝试
def refEquals[A <% AnyRef, B <% AnyRef](a: A, b: B) = a eq b
然后在运行refEquals(1,2)
时,我们发现Predef
中有隐式方法,包括int2IntegerConflict
来阻止此类转换。
我试过了:
def refEquals(a: Any, b: Any) = a match {
case x: AnyRef => b match {
case y: AnyRef => x eq y
case _ => false
}
case x: Any => b match {
case y: AnyRef => false
case y: Any => x == y
}
}
但是这不起作用(refEquals(1.0, 1.0)
给出false
)出于Rex Kerr给出的理由:Strange pattern matching behaviour with AnyRef
那么我们如何实现这样的方法呢?
编辑:应该说“引用类型的引用相等,或原始类型的值相等”。
编辑:这是使用Rex答案的方法的方法,适用于任何需要此功能且不喜欢打字的人:
def refEquals(a: Any, b: Any) = a match {
case x: Boolean if b.isInstanceOf[Boolean] => x == b
case x: Byte if b.isInstanceOf[Byte] => x == b
case x: Short if b.isInstanceOf[Short] => x == b
case x: Char if b.isInstanceOf[Char] => x == b
case x: Int if b.isInstanceOf[Int] => x == b
case x: Float if b.isInstanceOf[Float] => x == b
case x: Double if b.isInstanceOf[Double] => x == b
case x: Long if b.isInstanceOf[Long] => x == b
case _ => a.asInstanceOf[AnyRef] eq b.asInstanceOf[AnyRef]
}
答案 0 :(得分:5)
对于基本类型,引用相等性是未定义的,因为它们不是引用。在这种情况下,唯一的平等概念是价值平等。
但是,如果您希望代码同时使用基元和引用类型,则可以使用'=='并确保传递不重新定义'equals'的对象,或者定义自己的相等对象并传递它周围。您可以使用'scala.math.Equiv [T]'。
def myRefEquals[A](x: A, y: A)(implicit eq: Equiv[A]) {
eq.equiv(x, y)
}
implicit def anyRefHasRefEquality[A <: AnyRef] = new Equiv[A] {
def equiv(x: A, y: A) = x eq y
}
implicit def anyValHasUserEquality[A <: AnyVal] = new Equiv[A] {
def equiv(x: A, y: A) = x == y
}
println(myRefEquals(Some(1), Some(1)))
这假设您希望两个对象具有相同的类型。
答案 1 :(得分:4)
首先捕获所有原语,然后通过eq:
def refEquals(a: Any, b: Any) = a match {
case x: Boolean => b match {
case y: Boolean => x==y
case _ => false
}
case x: Byte =>
...
case _ => a.asInstanceOf[AnyRef] eq b.asInstanceOf[AnyRef]
}