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

Lui*_*hys 1 scala equals

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

eq仅定义于AnyRef.如果我们尝试

def refEquals[A <% AnyRef, B <% AnyRef](a: A, b: B) = a eq b
Run Code Online (Sandbox Code Playgroud)

然后在运行时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
  }
}
Run Code Online (Sandbox Code Playgroud)

但是由于Rex Kerr refEquals(1.0, 1.0)给出false的原因,这不起作用(给出):与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]
}
Run Code Online (Sandbox Code Playgroud)

Iul*_*gos 5

对于基本类型,引用相等性是未定义的,因为它们不是引用.在这种情况下,唯一的平等概念是价值平等.

但是,如果您希望代码同时使用基元和引用类型,则可以使用"=="并确保传递不重新定义"等于"的对象,或者定义自己的相等对象并传递它.你可以使用'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)))
Run Code Online (Sandbox Code Playgroud)

这假设您希望两个对象具有相同的类型.