如果我有一个父子,它定义了一些方法.foo(),如下所示:
class Parent {
public void foo(Parent arg) {
System.out.println("foo in Function");
}
}
class Child extends Parent {
public void foo(Child arg) {
System.out.println("foo in ChildFunction");
}
}
当我这样打电话给他们时:
Child f = new Child();
Parent g = f;
f.foo(new Parent());
f.foo(new Child());
g.foo(new Parent());
g.foo(new Child());
输出是:
foo in Parent
foo in Child
foo in Parent
foo in Parent
但是,我想要这个输出:
foo in Parent
foo in Child
foo in Parent
foo in Child
我有一个扩展Parent类的Child类。在Child类中,我想“部分覆盖”Parent的foo()
,也就是说,如果参数arg
的类型是Child,则调用Child的foo()
而不是Parent foo()
1}}。
当我作为一个孩子打电话给f.foo(...)
时,这很好用;但如果我从g.foo(...)
中的父别名引用它,那么无论foo(..)
的类型如何,都会调用父arg
。
据我所知,我期待的不会发生,因为Java中的方法重载是早期绑定(即在编译时静态解析),而方法重写是后期绑定(即在编译时动态解析),因为我定义了一个技术上不同的参数类型的函数,我在技术上用一个不同的定义重载Parent的类定义,而不是覆盖它。但是我想要做的是在概念上“部分重写”。foo()
的参数是父{q}}参数的子类。
我知道我可以在Child中定义一个桶覆盖foo()
来检查arg的实际类型是父类还是子类并正确传递它,但是如果我有二十个Child,那将是很多类型不安全的重复代码。
在我的实际代码中,Parent是一个名为“Function”的抽象类,它只抛出foo(Parent arg)
。这些孩子包括“多项式”,“对数”等,而.foo()包括Child.add(Child),Child.intersectionsWith(Child)等等。并非Child.foo(OtherChild)的所有组合都是可解决的。事实上,甚至所有Child.foo(儿童)都无法解决。所以我最好定义所有未定义的内容(即抛出NotImplementedException),然后只定义那些可以定义的内容。
所以问题是:有没有办法只覆盖父亲的foo()的一部分?或者有更好的方法来做我想做的事情吗?
编辑:
@Zeiss:如果我使用Double Dispatch,就像这样:
NotImplementedException()
我得到了无限的递归:
class Parent {
public void foo(Parent arg) {
System.out.println("foo in Parent");
}
}
class Child extends Parent {
public void foo(Parent arg) {
System.out.println("foo in Child(Parent)");
arg.foo(this);
}
public void foo(Child arg) {
System.out.println("foo in Child(Child)");
}
}
执行(stack):
StackOverflowError: ...
...
at sketch_apr25a$Child.foo(sketch_apr25a.java:35)
...
(output):
...
foo in Child(Parent)
...
时。其余的似乎很好,因为输出是:
g.foo(new Child());
为什么会这样? g是Parent的别名,但它正在访问Child的foo(Parent)?
答案 0 :(得分:3)
这不是Double Dispatching的用例吗?
更新
class Function {
public void add(Function f) {
f.addMe(this);
}
public void addMe(Function f) {
// Default case
throw NotImplementedException();
}
public void addMe(Logarithmic log) {
// Code that handles the real
}
}
class Logarithmic extends Function {
// This object supports adding
public void add(Function f) {
f.addMe(this);
}
}
Logarithmic log = new Logarithmic();
log.add(new Function());
log.add(new Logarithmic());
Function f = log;
f.add(new Function());
f.add(new Logarithmic());
答案 1 :(得分:0)
我通过明确覆盖foo(Parent arg)
中的Child
来实现这一点 -
class Parent {
public void foo(Parent arg) {
System.out.println("foo in Parent");
}
}
class Child extends Parent {
@Override
public void foo(Parent arg) {
System.out.println("foo in Child(Parent)");
if (arg instanceof Child) {
foo((Child)arg);
} else {
super.foo(arg);
}
}
public void foo(Child arg) {
System.out.println("foo in Child(Child)");
}
}
这似乎符合
的逻辑我想“部分覆盖”Parent的foo(),也就是说,如果参数arg的类型是Child,则调用Child的foo()而不是Parent的foo()。
但实际上,您必须覆盖该方法,而不是“部分覆盖”该方法。