【问题标题】:In Java, is it possible to require implementations of an interface to override Object methods?在 Java 中,是否可以要求实现接口来覆盖 Object 方法?
【发布时间】:2012-08-17 16:06:05
【问题描述】:

是否可以要求实现一个接口来覆盖Object 方法?

例如,如果我有一个通常用作HashMaps 中的键的接口,我可能希望要求该接口的所有实现都覆盖hashCode()equals() 方法。

但是,如果我有以下界面...:

public interface MyInterface(){
  @Override
  public int hashCode();

  @Override
  public boolean equals(Object o);
}

...以下实现编译:

public class MyImplementation(){
}

它不需要重写hashCode()equals() 的方法,因为它从Object 继承了这些方法。

一种方法是改用抽象类而不是接口:

public abstract class MyAbstractClass(){
  @Override
  public abstract int hashCode();

  @Override
  public abstract boolean equals(Object o);
}

那么任何扩展这个抽象类的类都需要覆盖hashCode()equals()

// doesn't compile - requires implementation of hashCode() and equals()
public class MyClass extends MyAbstractClass {
}

// does compile
public class MyClass extends MyAbstractClass {
  @Override
  public int hashCode(){
    // calculate hashcode
  }

  @Override
  public boolean equals(Object o){
    // check equality
  }
}

我的猜测是,这两者的区别在于抽象类是Object,所以它在层次结构中低于Object,所以所有扩展都需要满足抽象类中的约定。而接口不是Objects,所以不要坐在层次结构中,但是接口的任何实现都必须是Object,此时它继承了Object方法,因此满足接口'契约'。

但是,回到我最初的问题...有没有办法要求接口的实现覆盖Object 方法?

【问题讨论】:

  • 不,第一个子类满足合同。如果实现类的前一个类实现了所有接口的方法,则“契约”已经满足。

标签: java interface abstract-class


【解决方案1】:

没有办法只使用接口来完成你想要的。

通过强制使用抽象基类来实现此目的的另一种(可能更清晰)方法如下:

public abstract class MyAbstractClass {
  @Override public final int hashCode() { return hashCodeImpl(); }
  @Override public final boolean equals(Object o) { return equalsImpl(o); }

  protected abstract int hashCodeImpl();
  protected abstract boolean equalsImpl(Object o);
}

【讨论】:

  • 在我原来的问题中,有什么理由比抽象类更喜欢这样的抽象类吗?
  • @amaidment - 老实说,我没有意识到您可以覆盖具体方法并再次使其抽象(我假设您的示例无法编译)。快速测试确认它确实可以编译,但对我来说仍然很奇怪。
  • 我建议这比我的问题中的方法弱 - 如果我有另一个抽象类扩展您的 MyAbstractClass 并实现 hashCodeImpl() 和 equalsImpl(),然后创建该抽象类的实现- 然后我可以通过 a) 覆盖实际的 hashCode() 和 equals() 方法或 b) 通过覆盖 hashCodeImpl() 和 equalsImpl() 方法来覆盖 hashCode() 和 equals() 方法。对我来说,这似乎是糟糕的设计。
  • @amaidment - 不,你不能,因为我将 equals()hashCode() 方法设置为最终方法,因此它们不能被任何其他子类覆盖。
【解决方案2】:

没有。 Java 无法表达这种要求。一个抽象类怎么这样?

public abstract class MyAbstractClass(){
  @Override
  public int hashCode(){
    return myOverrideHashCode();
  }

  @Override
  public boolean equals(){
    return myOverrideEquals();
  }

  protected abstract int myOverrideHashCode();

  protected abstract booleans myOverrideEquals();
}

【讨论】:

    猜你喜欢
    • 2015-04-29
    • 2011-08-04
    • 1970-01-01
    • 2020-12-24
    • 1970-01-01
    • 2021-11-20
    • 1970-01-01
    • 2014-07-17
    • 1970-01-01
    相关资源
    最近更新 更多