检查任何类型的引用相等性的方法

时间:2011-11-10 22:11:04

标签: scala equals

我正在尝试创建一个与任何类型的引用相等匹配的方法,包括基元。怎么做到最好?

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

2 个答案:

答案 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]
}