[英]Use overridden method from subclass
我有A
班:
private static class A
{
public void foo()
{
Sub sub = new Sub();
sub.bar();
}
protected class Sub
{
protected void bar()
{
System.out.println("bar from A");
}
}
}
我想扩展它以对其子类Sub
bar()
稍加修改。
private static class B extends A
{
protected class Sub extends A.Sub
{
@Override
protected void bar()
{
System.out.println("bar from B");
}
}
}
如果我现在打电话给我
B b = new B();
b.foo();
我从A获得酒吧 ,但我从B获得酒吧 。
我也可以解决覆盖foo()
的问题。 但是foo()
是一个巨大的方法,如果我简单地复制它,我将得到冗余代码。 我不能将其拆分成多个较小的。
有没有一种方法可以在不覆盖foo()
情况下调用新的bar()
foo()
?
在A.foo()
您将创建A.Sub
的实例。 这就是为什么bar()
的A.Sub
被调用,而不是bar()
的B.Sub
。
一种可能的解决方案是更换
Sub sub = new Sub();
与:
Sub sub = getSub();
然后在A:
protected Sub getSub()
{
return new Sub();
}
在B中:
@Override
protected Sub getSub()
{
return new Sub();
}
B
的实例将产生B.Sub
的实例,而A
的实例将产生A.Sub
的实例。
您正在为Java语言的一个相当尴尬的概念( 称为“阴影”)而苦苦挣扎。 您知道通过B extends A
,您将重写B
中也定义的A
所有非私有实例方法。 相反,您可能知道字段没有被覆盖。 如果定义在两个同名的场A
和B
,存在两个领域,其中在子场B
阴影在超类领域的A
,而无需更换其使用A
。
内部类也是如此。 这意味着A.Sub
和B.Sub
是两个不同的类,就像两个(假设的)字段A.foo
和B.foo
是不同的一样。 A.Sub
仅由B.Sub
。 因此,在A
定义此调用时,调用new Sub()
将创建A.Sub
的实例, B.Sub
在B
定义时将创建A.Sub
的实例。 为了模拟多态性,您需要以某种方式获取涉及的方法调用,以触发Java的动态调度。 有两种方法可以做到这一点:
定义一个工厂方法,您可以重写该方法来创建所需的实例:
class A { class Sub { void doSomething() { System.out.println("A.Sub"); } } Sub make() { return new Sub(); } // Returns B.Sub } class B extends A { class Sub extends A.Sub { // Shadows A.Sub void doSomething() { System.out.println("B.Sub"); } @Override Sub make() { return new Sub(); } // Returns B.Sub, also when called within A }
使A.Sub
到B.Sub
层次结构是多态的:
class A { class Sub { void invoke() { doSomething(); } // Invokes outer method virtually } void doSomething() { System.out.println("A"); } } class B extends A { class Sub extends A.Sub { } // Shadows A.Sub @Override void doSomething() { System.out.println("B"); } }
您需要在对象中注入Sub
来实现这一点。 如果让它位于类A
构造函数中,则它仅对A.Sub
具有可见性。
然后,为A
构造A
接受A.Sub
和子类的构造函数:
public A(Sub sub) {
this.sub = sub;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.