모든 필드를 반복하고 개인 필드의 경우 해당하는 방법을 스칼라로 찾는이 솔루션이 등장했습니다. 실제로 사례 클래스에는 동일한 이름의 메서드를 통해 액세스 할 수있는 private 멤버가 있습니다.
implicit class ReallyEqual[T](a: T) {
import java.lang.reflect.Modifier._
def ==:==[U](b: U): Boolean = {
val fieldsA = a.getClass.getDeclaredFields
val methodsA = a.getClass.getDeclaredMethods
val mapA = (methodsA.toList map (z => (z.getName(), z))).toMap
val fieldsB = b.getClass.getDeclaredFields
val methodsB = b.getClass.getDeclaredMethods
val mapB = (methodsB.toList map (z => (z.getName(), z))).toMap
fieldsA.length == fieldsB.length &&
(true /: (fieldsA zip fieldsB)){ case (res, (aa, bb)) =>
if(((aa.getModifiers & STATIC) != 0) || ((bb.getModifiers & STATIC) != 0)) { res // ignore
} else if(((aa.getModifiers & (PRIVATE | PROTECTED)) == 0) && ((bb.getModifiers & (PRIVATE | PROTECTED)) == 0)) {
res && aa == bb && aa.get(a) ==:== bb.get(b)
} else if((mapA contains aa.getName) && (mapB contains bb.getName)) {
res && mapA(aa.getName).invoke(a) == mapB(aa.getName).invoke(b)
} else res
}
}
}
trait EqualBad {
override def equals(other: Any) = false
}
case class MyCaseClass(x: Int, y: List[Int]) extends EqualBad
MyCaseClass(1, List(1, 2)) ==:== MyCaseClass(1, List(1, 2)) // true
MyCaseClass(1, List(1, 2)) ==:== MyCaseClass(1, List(2, 2)) // false
MyCaseClass(1, List(1, 2)) ==:== MyCaseClass(2, List(1, 2)) // false
MyCaseClass(1, List(1, 2)) == MyCaseClass(1, List(1, 2)) // false
당신도 방법의 마지막 ==을 변경하여 더 재귀 할 수 ReallyEqual
에 == : ==
주의 : int로하지 않기 때문에, 정수에 대해 작동하지 않습니다 모든 필드 또는 방법. 예 : 1 == : == 2는 true를 반환합니다.
사례 클래스의 객체에서는 사례 클래스 값에만 관심이있는 경우 'productIterator.toList'를 사용할 수 있습니다. – pedrofurla
productIterator.toList가 작동하지 않았습니다. 인스턴스를 목록에 넣으면됩니다. – ttt
두 개체를 모두 반사시키고 필드와 값을 비교하십시오. – Ashalynd