【问题标题】:call method of child from instance of type Parent从 Parent 类型的实例调用 child 的方法
【发布时间】:2018-12-03 21:55:13
【问题描述】:

我必须做以下equals方法:

public boolean equals(ParentClass pa) {
    if (!(pa instanceof ChildClass))
        return false;
    boolean sameID = ID.equals(pa.getID());
    return super.equals(pa) && sameID;
}

ChildClass 类是 ParentClass 类的子类,这就是它的 equals 方法。方法 getId() 仅在 ChildClass 中,但我需要知道如何让方法 pa.getID() 工作,有什么方法可以在这里进行转换吗?因为我得到一个错误,编译器不能确定 pa 是否是 Child 的一个实例。

这是我得到的错误:

Error:(19, 73) java: cannot find symbol
  symbol:   method getID()
  location: variable pa of type ParentClass

我需要方法是 ParentClass 类型,因为当 ParentClass 类型的对象而不是错误时,函数应该返回 false。

任何帮助将不胜感激。

【问题讨论】:

  • 请在堆栈跟踪中提供完整的错误。
  • equals 应该使用Object,而不是ParentClass
  • 你试过这个吗:ChildClass pa2 = (ChildClass) pa;然后使用 pa2.getID();?
  • 是的,现在可以了,这就是问题所在,谢谢@Spara

标签: java object


【解决方案1】:

检查对象的类型并确保它是ChildClass 的实例后,只需将其转换为ChildClass 类型并使用它:

public boolean equals(ParentClass pa) {
if (!(pa instanceof ChildClass))
    return false;
ChildClass child = (ChildClass) pa;
boolean sameID = ID.equals(child.getID());
return super.equals(child) && sameID;
}

【讨论】:

  • equals 应该采用 Object,而不是 ParentClass。请不要从 OP 问题中传播不好的部分
  • 我其实很冷静,虽然你可能不同意,但我的说法并没有什么不礼貌的地方。重载 equals 是一种不好的做法,作为有经验的程序员提供答案,我们应该在机会出现时尽最大努力教授更好的做法。如果我的任何同事向我展示原始代码,我也会这样做。
  • @Krease 当然重载等于是个坏主意!但我认为还是只关注用户的问题,尽量不要让他对很多变化感到困惑!
  • 覆盖equals 是Java 编程的基本部分。指出纠正不良做法的微小变化不应令人困惑。这就是让 StackOverflow 上的答案对每个人都更有用的原因。
【解决方案2】:

在覆盖equals 时,遵循一个有用的通用模式。我将在此处提供一个带有更正的版本,并在下面概述这些更正:

@Override
public boolean equals(Object o) {
    if (this == o) { return true; }
    if (!super.equals(o) 
        || o == null 
        || getClass() != o.getClass()) { 
            return false; 
    }
    ChildClass other = (ChildClass) o;
    return this.getID().equals(other.getID());
}

首先,您通常可以在equals 的实现之间复制粘贴的内容:

  • 始终@Override equals 方法 - 这将有助于识别您意外重载它的问题(相同的方法名称,不同的参数类型)。重载equals 是一种不好的做法,会导致问题。

  • == 开始检查 - 如果通过,则无需浪费 CPU 周期来执行更多逻辑。虽然这实际上只是一个小的优化,但它是一个有用的最佳实践。

  • 如果您要扩展 Object 以外的类,请检查 super 是否相等。

  • 检查以确保类相同。请注意,这不是instanceof 检查。

    • 记住,equals 必须是对称的:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才应该返回 true。
    • 如果您使用instanceof,您可能会遇到parent.equals(child) == truechild.equals(parent) == false - 这很糟糕。
    • 在某些情况下,instanceof 是可以的,但大多数情况下检查类相等性更安全、更正确。

现在,类特定的东西:

  • Object 参数转换为您的类类型,并比较您关心的那些是否相等。
    • 请注意,this 上的调用应该与 other 上的调用匹配 - 在您的情况下,我将两者都更改为调用 getID() 方法。或者,两者都可以引用私有成员 ID - 但它们应该是一致的。

最后,不要忘记 equalshashCode 是一对 - 你应该始终一起实现它们。 (我知道你没有特别问这个问题,但我指出这是人们在实施equals 时常犯的错误)

  • 如果根据 equals(Object) 方法,两个对象相等,则对两个对象中的每一个调用 hashCode 方法必须产生相同的整数结果。如果你只覆盖 equals() 而不是 hashCode() 你的类就违反了这个约定。

我希望这可以帮助您和其他任何人在实施 equals 时遇到问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-08
    • 1970-01-01
    • 2014-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多