简化演示代码以显示我的问题。
class Base {
public String toString() { return "Base"; }
};
class A extends Base {
public String toString() { return "A"; }
};
class Test {
public void test1() {
A a = new A();
Base b = (Base)a; // cast is fine, but b is the same instance as a
System.out.println(b.toString()); // want "Base", but get "A"
}
private String testB(Base b) {
return b.toString(); // this should return "Base"
}
public void test2() {
System.out.println( testB(new A()) ); // want "Base", but get "A"
}
};
我尝试了强制转换方法(test1)和辅助方法(test2)。
到目前为止,我发现需要Base的复制构造函数来创建一个真正的Base对象。
是否有一个不需要重复对象的方法?
一些背景信息:
我得到一个A的实例,我知道它的基类有一个很好的方法,我想用它来代替覆盖的版本。我更喜欢既不修改A类也不修改B类(尽管副本c' tor无论如何都是一个很好的增强;)
答案 0 :(得分:7)
直接从课程A
,您可以super.toString();
使用toString()
在Base
上执行A
。
但是,从外部类A
开始,您无法以这种方式调用超类实现,这样做会破坏封装。如果你想暴露超类实现,那么你仍然可以,但你必须在System.out.println(Base.class.getMethod("toString", null).invoke(new A(), null)); //Prints "A"
上提供一个直接公开它的单独方法。
即使使用基于琐碎反射的方法,you still won't be able to access it:
如果底层方法是实例方法,则使用动态方法查找
调用它
MethodHandles.lookup().findSpecial
...并且使用IllegalAccessException
将无法在子类外部工作,因为必须在您具有私有访问权限的情况下调用它(否则您将获得-core
。)
我承认,如果没有字节码操作,我可能会直接在Java中使用一些奇怪且奇妙的方式来做这件事,但即使你可以,也可以说这样做,除了古怪的技术演示之外,你当然不应该。
答案 1 :(得分:3)
你需要创建B实例(复制构造函数),如果你正在使用A实例,你总会得到" A"无论你是否投了它。