私はすべてのフィールドを繰り返し処理するこのソリューションを考え出し、プライベートフィールドの場合は対応するメソッドをスカラーで検索します。実際、ケースクラスには、同じ名前のメソッドでアクセスできるプライベートメンバーがあります。
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