继承 - 在子类中使用 super.equals() 来覆盖超类 equals 中使用的方法

Kub*_*tny 5 java inheritance equals

我一直在测试代码并偶然发现了一个问题:您是否应该在子类中调用可以覆盖超类方法super.equals()中使用的某些方法的方法?equals()

让我们考虑以下代码:

public abstract class Item {
    private int id;
    private float price;

    public Item(int id, String name, float price, String category) {
        this.id = id;
        this.name = name;
        this.price = price;
        this.category = category;
    }

    public int getID() {
        return id;
    }

    public float getPrice() {
        return price;
    }

    @Override
    public boolean equals(Object object){
        if(object instanceof Item){
            Item item = (Item) object;
            if( id == item.getID()
                && price == item.getPrice())                    
            { return true; }
        }
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

以及 DiscountedItem 的子类:

public class DiscountedItem extends Item {
    // discount stored in %
    private int discount;

    @Override
    public boolean equals(Object object) {
        if(object instanceof DiscountedItem){
            DiscountedItem item = (DiscountedItem) object;
            return (super.equals(item)
                    && discount == item.getDiscount()
            );
        }
        return false;
    }

    public int getDiscount() {
        return discount;
    }

    @Override
    public float getPrice() {
        return super.getPrice()*(100 - discount);
    }    
}
Run Code Online (Sandbox Code Playgroud)

我刚刚重读了Angelika Langer 的 equals() 秘密,她甚至指出:

一致认为,如果该类具有除 Object 之外的超类,则应调用 super.equals()。

但我认为子类何时重写某些方法是非常难以预测的。例如,当我DiscountedItem使用 equals 比较 2 个对象时,将调用 super 方法并将item.getPrice()其动态分派到子类中的正确方法DiscountedItem,而使用变量直接访问另一个价格值。

那么,这真的取决于我(因为我应该正确实现该方法)还是有办法解决它?

Mat*_*att 4

直接比较实例变量,而不是将实例变量与其相关的 getter 方法进行比较。

例如,改变

&& price == item.getPrice())
Run Code Online (Sandbox Code Playgroud)

&& this.price == item.price)
Run Code Online (Sandbox Code Playgroud)

getter 方法是不必要的,因为私有实例变量只能在类结构之外访问。


笔记:

我之前推荐过以下内容:

&& this.getPrice() == item.getPrice())
Run Code Online (Sandbox Code Playgroud)

虽然它适用于问题的示例,但它并不适合所有情况。考虑子类是否这样DiscountedItem声明该方法:getPrice

@Override
public float getPrice() {
    return Math.floor(super.getPrice());
} 
Run Code Online (Sandbox Code Playgroud)

这将导致错误的等价:

DiscountedItem firstItem = DiscountedItem(1, "", 1.1, "");
DiscountedItem secondItem = DiscountedItem(1, "", 1.0, "");
firstItem.equals(secondItem); // Returns true despite different prices.
Run Code Online (Sandbox Code Playgroud)