【发布时间】:2011-08-04 10:11:03
【问题描述】:
我有一些类继承 SubClass
我目前的解决方案是非常样板:
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() 不是指在超类的上下文中执行相同的继承方法,而是指被覆盖的方法实现。由于 Object 中不存在 m1(),所以我另外得到一个编译器错误...
将 TASK 放在 SuperClass 中受保护的最终 helper() 方法中并调用 helper() 而不是复制 TASK 将不起作用,因为这样总是会调用 SuperClass.m2()。
我能想到的唯一选择是缓慢、复杂和不安全:使用类型标记作为参数,即 SuperClass 中的protected final void m1(Class<? extends SuperClass> clazz),并通过反射完成 TASK(需要将 m2() 设为公共静态或使用 setAccessible(true ) 在 m2()) 上。
你知道更好的解决方案吗?奥普?也许是一些可以将方法注入类的框架(如在 C# 中)?还是我错过了什么???
【问题讨论】:
-
您能否详细说明一下任务的不同之处?我怀疑设计问题比代码问题更多。
-
任务的不同之处在于比较的值:由该子类添加的那些字段。详细说明:我已经实现了具有默认值约束的混合类型 equal(),而不是忽略子类值字段。详情请见angelikalanger.com/Articles/JavaSolutions/SecretsOfEquals/…。在 Angelika 的术语中,m1() 是 _navigateClassHierarchy(),m2() 是 _compareFields()。
-
如果我理解正确,
_compareFields()也会比较子类中的附加字段。因此,我提出的super.m2()方法应该适用于此(类似于if( super._compareFields() ) { /*compare additional fields*/})。 -
是的,Thomas,我可以做到,谢谢。它将大大简化代码:对于 o1.equals(o2),我可以简单地调用 this._compareFields(o2) 和 o2._compareFields(this),而不需要 _navigateClassHierarchy()。请参阅我自己的回答,了解如何避免某些检查被执行两次,这就是首先实施 _navigateClassHierarchy() 的原因。获得一个关于如何用 Java 解决我的问题的一般答案,而不是重新设计,仍然很有趣:对于以后的类似情况,用 Java 解决这个问题也可以让我们对语言有更多的了解......
标签: java inheritance code-reuse super dynamic-dispatch