为什么我不能使用equals继承? [英] Why should I not use equals with inheritance?

查看:407
本文介绍了为什么我不能使用equals继承?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我阅读一本Java书时,作者已经说过,在设计一个类时,使用带继承的 equals()通常是不安全的。例如:

When I read a Java book, author has said that, when designing a class, it's typically unsafe to use equals() with inheritance. For example:

public final class Date {
    public boolean equals(Object o) {
         // some code here
    }
}

在上面的课程中,我们应该把 final ,因此其他类无法从此继承。而我的问题是,为什么在允许另一个类从此继承时它是不安全的?

In the class above, we should put final, so other class cannot inherit from this. And my question is, why it is unsafe when allow another class inherit from this?

推荐答案

因为它很难(不可能?)做得对,特别是 对称属性

Because it's hard (impossible?) to make it right, especially the symmetric property.

假设你有类 Vehicle 和class Car extends Vehicle Vehicle.equals()产生 true 如果参数也是 Vehicle 并且具有相同的重量。如果你想实现 Car.equals(),只有当参数也是汽车时它才会产生 true ,并且除了重量,它还应该比较制造,引擎等。

Say you have class Vehicle and class Car extends Vehicle. Vehicle.equals() yields true if the argument is also a Vehicle and has the same weight. If you want to implement Car.equals() it should yield true only if the argument is also a car, and except weight, it should also compare make, engine, etc.

现在想象下面的代码:

Vehicle tank = new Vehicle();
Vehicle bus = new Car();
tank.equals(bus);  //can be true
bus.equals(tank);  //false

第一次比较可能会产生 true 如果巧合坦克和公共汽车有相同的重量。但由于坦克不是汽车,将它与汽车相比将总是产生

The first comparison might yield true if by coincidence tank and bus have the same weight. But since tank is not a car, comparing it to a car will always yield false.

你工作很少-arounds:

You have few work-arounds:


  • 严格:两个对象相等当且仅当它们完全相同时类型(和所有属性相等)。这很糟糕,例如当你几乎没有子类添加一些行为或装饰原始类。一些框架也是你的类的子类,你没有注意到(Hibernate,带有CGLIB代理的Spring AOP ......)

  • strict: two objects are equal if and only if they have exactly the same type (and all properties are equal). This is bad, e.g. when you subclass barely to add some behaviour or decorate the original class. Some frameworks are subclassing your classes as well without you noticing (Hibernate, Spring AOP with CGLIB proxies...)

松散:如果它们的类型有两个对象是相等的是兼容的,它们具有相同的内容(语义上)。例如。如果它们包含相同的元素,则两个集合相等,一个是 HashSet 并且另一个是 TreeSet (感谢 @veer 指出这一点。)

loose: two objects are equal if their types are "compatible" and they have same contents (semantically). E.g. two sets are equal if they contain the same elements, it doesn't matter that one is HashSet and the other is TreeSet (thanks @veer for pointing that out).

这可能会产生误导。取两个 LinkedHashSet s(其中插入顺序是合同的一部分)。但是,由于 equals()只考虑原始 Set 合同,因此比较结果为 true 即使对于明显不同的对象:

This can be misleading. Take two LinkedHashSets (where insertion order matters as part of the contract). However since equals() only takes raw Set contract into account, the comparison yields true even for obviously different objects:

Set<Integer> s1 = new LinkedHashSet<Integer>(Arrays.asList(1, 2, 3));
Set<Integer> s2 = new LinkedHashSet<Integer>(Arrays.asList(3, 2, 1));
System.out.println(s1.equals(s2));


这篇关于为什么我不能使用equals继承?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆