Polymorphism允许程序员继承,覆盖或重载父类的实例方法。
但是,它不允许在父类中使父类的实例方法更具限制性。即它不允许使用父类实例方法的相同名称,在子类中声明为私有。
如果子类没有覆盖它,JVM也会识别实例方法的父类版本。
同样,为什么JVM不识别实例方法的父类版本,如果子类使其更具限制性?
子类中父类的限制性更强的方法可以被视为子类特定的方法,而不是编译器重写的方法。
答案 0 :(得分:17)
这一切都是为了遵循Liskov Substitution Principle。
为了使面向对象编程中的继承行为符合预期,子类应该能够替换父类实例而不会破坏类的用户。
使子方法更具限制性基本上是说“我不希望这种方法可见”。在这种情况下让JVM自动替换父类实现只会增加大量的混淆 - 只是改变调用行为可能会导致非常意外的行为,甚至完全在子类中......
答案 1 :(得分:2)
子类中父类的限制性更强的方法可视为子类特定方法
Java作者可以实现这一点。还有许多其他的东西,比如臭名昭着的多重继承。但它会使语言变得更加复杂,从而获得很少的好处。
如果你需要私人版本的父方法,你为什么不给它不同的名字?因为它只会从你的孩子班级打来,所以没有太大区别。
答案 2 :(得分:2)
Java创建者认为Java应该尽可能简单,你的问题可能会导致代码出现问题:
class A {
public void methodA(){
}
}
class B extends A {
@Override
private void methodA(){
}
}
//
public static void main(String... args){
A a = new B();
a.methodA(); // Should call the overridden method but as it's private it can't work.
}
你为这个案例提供了一个解决方案,但它有一个缺陷:
class A {
public void methodA(){
}
public void methodB(){
methodA();
}
}
class B extends A {
@Override
protected void methodA(){
}
}
//
public static void main(String... args){
A a = new B();
a.methodB(); // Will methodA from A be called or from B ?
}
解决方案很复杂,违背了java哲学。这或多或少是为什么使用当前的解决方案;即使不能使用特定功能,也会更简单。
答案 3 :(得分:0)
如果我理解正确,你说我应该写:
public class Foo
{
public int bar()
{
return 1;
}
}
public class Foo2 extends Foo
{
private int bar()
{
return 2;
}
public int barBar()
{
return bar();
}
}
public static void main(String[] args())
{
Foo2 foo2=new Foo2();
System.out.println(foo2.bar());
System.out.println(foo2.barBar());
}
然后,如果我创建一个类型为Foo2的实例并从类中调用bar,它应该调用Foo2.bar所以我应该返回2,但如果我从类外调用bar,它应该调用Foo.bar所以我回来了。
也就是说,上述程序的输出应为: 1 2
嗯,因为这是一个关于语言设计的问题,我想简单的答案是,“因为Java的设计师决定这样做。”
真正的问题是,为什么你希望它按照你描述的方式行事?你有一个应用程序,这将有用吗?在我看来,这只会令人困惑。
答案 4 :(得分:0)
您想要做的是使用组合将“父”类包装到另一个组中,而不是在要限制访问时继承。
因此,您创建了一个新类,其中包含您要作为成员包装的类,并通过设计自己的API提供对所需内容的访问。当然,你不能使用旧的新类,但这没有任何意义。如果那不是你想要的,我同意100%的Reed Copsey的回答(我同意100%,即使这是你想做的事)。