0

我有一些类继承 SubClass < MidClass < SuperClass 并希望为所有这些类执行一些向上的任务。TASK 相当复杂,仅在 3 个类中进行了微小的更改,我将它们移到了私有方法 m2() 中。

我目前的解决方案是非常样板:

class SuperClass {
  protected void m1() {
    //TASK (calls m2())
  }

  private void m2() {
    //...
  }
}

class MidClass extends SuperClass {
  protected void m1() {
    //same TASK (calls m2())
    super.m1();
  }

  private void m2() {
    //...
  }
}

class SubClass extends MidClass {
  protected void m1() {
    //same TASK (calls m2())
    super.m1();
  }

  private void m2() {
    //...
  }
}

我可以利用一些代码重用机制而不是复制 TASK 吗?

像下面这样的东西,m1() 只在 SuperClass 中,不起作用:

class SuperClass {
  protected final void m1() {
    //TASK (calls m2())
    if (!(this.getClass().equals(SuperClass.class))) {
      super.m1();
  }
}

因为 super.m1() 不是指在超类的上下文中执行相同的继承方法,而是指被覆盖的方法实现。由于 m1() 在 Object 中不存在,我另外得到一个编译器错误......

将 TASK 放入 SuperClass 中受保护的最终 helper() 方法中并调用 helper() 而不是复制 TASK 将不起作用,因为那时总是调用 SuperClass.m2() 。

我能想到的唯一选择是缓慢、复杂和不安全:使用类型标记作为参数,即protected final void m1(Class<? extends SuperClass> clazz)在 SuperClass 中,并通过反射完成任务(需要将 m2() 设为公共静态或在 m2() 上使用 setAccessible(true)) .

你知道更好的解决方案吗?奥普?也许是一些可以将方法注入类的框架(如在 C# 中)?还是我错过了什么???

4

3 回答 3

4

这个怎么样?

class SuperClass {
  protected void m1() {
    //TASK (calls m2())
  }

  protected void m2() {
    //...
  }
}

class MidClass extends SuperClass {

  protected void m2() {
    //...
  }
}

class SubClass extends MidClass {
  protected void m2() {
    //...
  }
}

m1方法是继承的,并且将始终调用该m2方法。由于m2受到保护,因此称为多态。因此,如果在SubClass实例上调用,SubClass.m2()将被调用。

于 2011-08-04T10:20:34.560 回答
0

我使用默认值约束而不是忽略子类值字段的混合类型 equals() 的具体示例的解决方案。而不是 Angelika Langer 的解决方案(请参阅http://www.angelikalanger.com/Articles/JavaSolutions/SecretsOfEquals/Equals-2.html)与私有方法 _compareFields() 和一个受保护的方法 _navigateClassHierarchy() 必须被复制到每个子类,仅使用受保护的方法 compareOwnFields(),必须在每个子类中正确覆盖该方法。

class SuperClass {
    // ...

    @Override
    public final boolean equals(final Object other) {
        if (other == this) { return true; }
        if (!(other instanceof SuperClass)) {
            return false;
        }
        final SuperClass otherSuperClass = (SuperClass) other;

        return compareOwnFields(otherSuperClass, false)  
        && otherSuperClass.compareOwnFields(this, true);
    }

    protected boolean compareOwnFields(final SuperClass other, 
        final boolean firstTraversal) {
        if (!firstTraversal) {
            return true;
        }
        if (field1 != other.getField1()) {
           return false;
        } 
        // compare other fields similarly ...
        return true;
    }

}    

class SubClass {
    // ...

    @Override
    protected boolean compareOwnFields(final SuperClass other, 
        final boolean firstTraversal) {
        if (other instanceof SubClass && !firstTraversal) {
            return true;
        if (other instanceof SubClass) {
            if (field1 != ((SubClass) other).getField1()) {
                return false;
            }
            // compare other fields similarly ...
            return super.compareOwnFields(other, firstTraversal);
        } else {
            if (field1 != DEFAULT_FIELD1) {
                return false;
            }
            // check other fields for default values similarly ..
            return super.compareOwnFields(other, firstTraversal);
        }
    }
}

但这一般不能回答我的问题,而是一种避免问题的重新设计。因此,非常欢迎您提供有关如何解决 Java 语言功能问题的进一步答案!

于 2011-08-05T17:53:37.670 回答
0

扩展我对 JB 答案的评论:

class SuperClass {
 protected void m1() {
   m2();
 }

 protected void m2() {
   System.out.println("start super task");
   System.out.println("end super task");
 }
}

class MidClass extends SuperClass {
  protected void m2() {
   super.m2();
   System.out.println("start mid task");
   System.out.println("end mid task");
  }
}

class SubClass extends MidClass {
 protected void m2() {
  System.out.println("start sub task");
  super.m2();
  System.out.println("end sub task");
 }
}

new SubClass().m1()产生这个结果:

开始子任务
开始超级任务
结束超级任务
开始中间任务
结束中间任务
结束子任务

请注意,所有 3 个版本m2()都按定义的顺序执行:启动 sub,然后以 super 和 mid 继续执行,并再次以 sub 结束。

于 2011-08-04T11:22:03.487 回答