为什么Java没有基于访问说明符的继承

为什么Java没有基于访问说明符的继承,java,inheritance,Java,Inheritance,在Java中,我们不能在继承类时指定private、protected或public。例如,下面的代码在Java中是不可能的。为什么? class A { public void display() { //Some implementation of display logic. } } class B extends **protected** A { public void show() { display();

在Java中,我们不能在继承类时指定private、protected或public。例如,下面的代码在Java中是不可能的。为什么?

class A {
    public void display() {
        //Some implementation of display logic.
    }
}

class B extends **protected** A
{
    public void show() {
         display();
         //some more logic.
    }
}

B obj = new B();
obj.show();
我不想要obj.display(),需要对外界隐藏它的实现。在C++中,我们可以使用基于访问修饰符的继承,但是在java中没有。我的问题是,如果我们想隐藏实现,我们如何实现这一点


为什么Java会在继承过程中删除访问修饰符,使用它的危害是什么?

请注意,不能降低方法或字段的可见性,因为它会导致将子类传递给需要超类的方法时出现问题。然而,你可以增加它

让我们看一个例子:

public static void displayFromA(A a){
    a.display();
}

由于
B
扩展了
A
,我们可以将
B
传递给此。如果
B
显示(
方法的可见性降低,此方法将不起作用。这将打破Liskov替换原则的前提,正式地说,如果
q(x)
是方法调用
显示(
然后
q(x)的能力的真值)
作为A的一个实例适用于
x
,但如果
x
是A的一个子类型,则不一定适用。

C++提供了允许将物理继承用作类实现细节的一部分的能力

C++的这个部分是在Barbara Liskov介绍了现在被称为“Liskov”的情况下设计的。为了满足Liskov替换原则,无论使用超类的实例,也可以使用子类的实例。在这种情况下,可以将B传递给期望A.< /P>的方法。 Java是在引入这一原则后设计的。在Java中,继承的物理机制仅用于从超类逻辑继承的类。要使用类的实现,而不是其接口,可以使用委托

从Stroustrup的“C++的设计和发展”中可以看出:

“基类的私有/公共区分比实现继承与接口继承的争论早了大约五年[Synder,1986][Liskov,1987]如果您只想继承一个实现,则在C++中使用私有派生。公共派生给派生类访问基类提供的接口的用户。私有派生留给基实现细节;即使通过显式接口,基类的公共成员也不可访问。为派生类提供。”


阻止访问底层display()的一种方法是重写它。例如,在B类中:

@Override
public void display() {
  throw new UnsupportedOperationException("Do not use B.display(), please use B.show() instead");
}
在B中,例如在show()中,调用super.display()

但是,这将在运行时捕获,而不是在编译期间。添加一些Javadoc,希望他们能够阅读它们。:-)

我不知道有什么方法可以添加像@NeverCallMe注释这样的东西,这样会在编译时被发现。有人知道这样做的诀窍吗


(补充)顺便说一句,我同意Java的设计者和其他人的回答,这是你通常不应该为了正确的面向对象性、Liskov和所有这些而做的事情。但这是一种有点笨拙的方式来做你想做的事情。

没有理由让类B有一个“is-a”如果您想对所有人隐藏该信息,请与A类关联

如果您只想重用类A中的代码,则可以让类B包装A的实例并将其委托给它,如下所示:

class B{
    //this is our delegate to A
    private A myA = new A();

    public void show() {
         myA.display();
         //some more logic.
    }
}

B obj = new B();
obj.show();

你想用基类的访问修饰符来实现什么?是的,更新的问题。我想他问为什么……在我看来,Ankit被设计成纯OO语言。而C++被设计成支持面向对象的范式。所以,java人认为C++中的这些东西会使事情变得更复杂,所以他们离开了java。所以如果你仍然有这样的PROSS,很明显你并没有完全转向java。你正在尝试用java实现C++。这不好。所以我建议你重新考虑一下你当前的OB的OO设计。我不知道代码> C++ +代码>,所以也许这句话有意义,但我不认为会有这样的。在
Java
中能够做到这一点的好处是,覆盖一个超类方法并降低它的可见性是没有意义的。从某种意义上说,子类
不是一个超类。如果是这样的话,并且你需要超功能,你总是有组合。@Ankizalani你不能,因为那样会如果某些方法需要一个
a
来运行
display(
打开,但是你通过了它B。你只能增加可见性。是的,我同意,但是为什么要为Java做出架构决定。一个原因(如上所述)是它会破坏Liskov替换原则。