为啥我们可以降低扩展类中属性的可见性?

Posted

技术标签:

【中文标题】为啥我们可以降低扩展类中属性的可见性?【英文标题】:Why can we reduce visibility of a property in extended class?为什么我们可以降低扩展类中属性的可见性? 【发布时间】:2014-09-03 09:16:36 【问题描述】:

我有两个班,@​​987654321@:

public class Parent 
    public String a = "asd";

    public void method() 

    

还有Child

public class Child extends Parent
    private String a = "12";

    private void method() 

    

Child 中,我尝试覆盖父method,这会产生cannot reduce visibility of a method 的编译时错误,这很好。

但是,为什么这个错误不适用于属性a?我还降低了a 的可见性,但它不会给出错误。

【问题讨论】:

【参考方案1】:

这是因为Parent.aChild.a 是不同的东西。 Child#method() @Overrides Parent#method(),因为它们是方法。继承不适用于字段。

来自Oracle JavaTM Tutorials - Inheritance,写道:

你可以在子类中做什么

继承的字段可以直接使用,就像任何其他字段一样。 您可以在子类中声明一个与超类中同名的字段,从而将其隐藏(不推荐)。 您可以在子类中声明不在超类中的新字段。

【讨论】:

Inheritance does not apply to fields. 看起来不是这样,如果我在Parent 中有public String b,那么我可以在Child 中访问它 @user2410148 是的,但这完全是由于访问,Child.a 没有继承 Parent.a。这也使得您可以在Child 中使用this.asuper.a - Child.a 不会被继承,类似于接口中的常量字段。 如果您可以向我指出一个明确说明您在上面所说的内容的资源,那将是一个很棒的帮助【参考方案2】:

你不能。您并没有降低 a 的可见性 - 您正在创建一个新的、单独的字段,也称为 a

【讨论】:

这样的做法不违反里氏替换原则吗?还是该原则仅适用于方法? @WandMaker 它是如何违反这一点的?如果您有Parent p;,那么p.a 仍然是同一个字段,即使它引用Child。要访问新字段,您需要使用 ((Child)p).a 我的意思是替代原则是说子类可以通过对基类的引用来使用。因此,如果我们在 child 中有一个公共成员变量,它将有效地覆盖基类中的同名变量。当我们在子类中声明一个具有相同名称的私有变量但没有收到任何警告/错误时,这一事实似乎表明,在使用子类的基类引用时可能会产生副作用,而这可能不是有意的。为什么只考虑公共方法作为合同的一部分,而不考虑公共变量? @WandMaker 使用基类引用时,只能访问基类的字段。 @WandMaker,可能。【参考方案3】:

您实际上是在为 Child 创建一个私有变量。所以,Child 有两个 a,一个是私有的,一个是公有的。下面的代码向您展示了如何访问两者。这些方法适用于整个类(父类)及其子类。因此,您会收到该方法的错误。

试试这段代码看看两个a:

public class Child extends Parent
    private String a = "12";

    //private void method() 

    public static void main(String[]args)
        Child c = new Child();
        Parent p = c;
        System.out.println(c.a + ", " + p.a);//12, asd

    


【讨论】:

以上是关于为啥我们可以降低扩展类中属性的可见性?的主要内容,如果未能解决你的问题,请参考以下文章

scala类中属性的可见性

为啥我们不能在 kotlin 中将类的可见性标记为“受保护”?

为啥在使用传统绑定时 bool 可以在没有转换器的情况下为可见性工作

php获取可见性

为啥 m 方法的可见性会以这种方式改变输出?我预计会发生相反的情况[重复]

在 C++ 中声明可见性/访问的方式有何不同?