结构化在运行时等于Scala
发布时间:2020-12-16 09:11:05 所属栏目:安全 来源:网络整理
导读:scala中是否有一些功能在运行时结构化比较两个对象?由于字段的数量,我宁可不必手动创建一个equals函数.这是一个单元测试,所以性能不是一个问题.我只需要一些反映在字段中的东西,并比较值. 背景:我有一个case类,从覆盖equals的特征扩展,因此不会生成结构性e
scala中是否有一些功能在运行时结构化比较两个对象?由于字段的数量,我宁可不必手动创建一个equals函数.这是一个单元测试,所以性能不是一个问题.我只需要一些反映在字段中的东西,并比较值.
背景:我有一个case类,从覆盖equals的特征扩展,因此不会生成结构性equals(squeryl KeyedEntity,related:Prevent Mixin overriding equals from breaking case class equality),现在我无法改变.这是一个单元测试,所以这两个实例都不会持久化. 解决方法
我想出了这个解决方案,它遍历所有字段,对于私有字段,在scala中找到一个相应的方法.事实上,案例类可以通过相同名称的方法访问私有成员.
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,2)) // true MyCaseClass(1,List(2,2)) // false MyCaseClass(1,2)) ==:== MyCaseClass(2,2)) == MyCaseClass(1,2)) // false 您甚至可以通过将ReallyEqual方法中的最后一个==更改为==:==来进行更多的递归 仔细:这对于整数是无效的,因为Int没有任何字段或方法.例如:1 ==:== 2将返回true. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |