代码重用“类型的所有对象都是相同的”模式

时间:2012-12-18 14:22:09

标签: java equals code-reuse boilerplate

我有许多类都覆盖它们的equals和hashCode方法,如下所示:

final class MyClass {
  public void statelessMethod() {
    // ...
  }

  @Override
  public boolean equals(Object obj) {
    return obj instanceof MyClass;
  }

  @Override
  public int hashCode() {
    return MyClass.class.hashCode();
  }
}

这个想法是,虽然班级没有任何改变new MyClass().equals(new MyClass())的状态,但应该总是如此。

我正在寻找的是一些我可以编写(或重用)的代码模式或实用程序类,它将尽可能多地删除样板文件。

背景

我正在使用这种模式来定义Guice模块,这样如果多个模块依赖于UtilModule(例如),我最终不会因同一类型的多个绑定而导致错误。

额外背景

此模式与Guice Servlets InternalServletModule重复,后者使用它来允许您在注入器配置中指定多个ServletModule模块,而不会复制作为该类的一部分提供的绑定。

回答部分评论的实际使用示例

final class UtilModule extends AbstractModule {
  public void configure() {
    // bindings and things
  }

  @Override
  public boolean equals(Object obj) {
    return obj instanceof UtilModule;
  }

  @Override
  public int hashCode() {
    return UtilModule.class.hashCode();
  }
}

多个模块的示例,取决于UtilModule(来自评论)

class Module1 extends AbstractModule {
  @Override
  protected void configure() {
    bind(SomeClass.class).to(SomeClassImpl.class);
    install(new UtilModule()); // needed by SomeClassImpl
  }
}

class Module2 extends AbstractModule {
  @Override
  protected void configure() {
    bind(MyService.class).in(Singleton.class);
    install(new UtilModule()); // needed by MyService
  }
}

class Main {
  public static void main(String[] args) {
    Injector injector = Guice.createInjector(
        new Module1(),
        new Module2());
    // ...
  }
}

1 个答案:

答案 0 :(得分:0)

您的类可以扩展一个实现equals和hashCode的公共基类。在这种情况下,您必须将MyClass的引用替换为this.getClass()

此外,instanceof不是您想要的,因为当obj是扩展当前类的类时,它也将返回true。这不仅不太可能是你想要的,它也会违反equals的合同,因为当你将一个基类的实例与一个扩展类的实例进行比较时,你调用equals方法的那个就重要了。 (派生的是instanceof base,但base不是派生的instanceof。)

基类中的实现看起来像这样:

@Override
public boolean equals(Object obj) {
   this.getClass().equals(obj.getClass())
}

@Override
public int hashCode() {
  return this.getClass().hashCode();
}

在一个不相关的注释中:当对象没有内部状态时,为什么不使用Singleton pattern