【问题标题】:Why does Java not impose a restriction to have the child class visibility greater than the parent class为什么Java不施加限制以使子类可见性大于父类
【发布时间】:2016-03-17 21:49:32
【问题描述】:

为什么可以在Java中创建一个可见性小于超类的子类。

package 1
public class Class1 {

    public Class1 hello(){
        Class1 c= new Class2();
        return c;
    }   
}


class Class2 extends Class1 {

     public Class1 hello() {
        System.out.println("In overriden method");
            return null;
    }    
}

假设 Class1 和 Class2 在同一个包中,Class2 的可见性是包私有的。

package 2
public class Major {
    public static  void main(String[] args) {
        Class1 ob = new Class1();
        ob.hello().hello();
    }
}

您会注意到,由于运行时多态性,将打印“In overriden method”。

在运行时,当Class2 位于具有包私有可见性的不同包中时,如何从main() 访问Class2hello() 方法?

Class2 不应该是可访问的,因此Class2 中的hello() 方法也不应该是可访问的。

【问题讨论】:

  • 没有什么可以阻止公共类从包 2 返回 Class2 的实例。
  • 不要使用引号,而是使用code-blocks(编辑器菜单中带有{} 图标的按钮)来保留格式。
  • 你为什么要强制这样的限制?没有意义
  • main 方法不能直接访问Class2,因为Class2 的存在以及它的作用是包1 的内部问题。但是,通过多态性,Class2 的实例可以作为Class1 引用传递给main,并且main 可以调用任何公共Class1 方法,即使该方法被Class2 覆盖。都是关于encapsulation
  • Class2 isnt 可访问,但根据定义,它实现的任何由 Class1 的合同表达的东西都是可访问的。你的问题没有意义。

标签: java polymorphism package public overriding


【解决方案1】:

protected 关键字(有点类似于包私有)是一种保护您的代码不被外部使用的方法,这正是您的示例中发生的情况。您不是直接使用Class2,而是使用Class1,这授予您间接使用受保护的Class2 的权利。

这是一个责任原则。 public Class1 负责授权外部包使用protected Class2。但这个责任也意味着Class1 的开发者必须知道为什么以及如何授予你这个权利。

extend Class1 在您的示例中没有实际意义,您的困惑可能来自于此。您不能从包外部实例化 Class2,但 Class1 可以。

【讨论】:

    【解决方案2】:

    实际上,考虑到所涉及方法的类型签名,它可能无法以任何其他方式工作。

    Class1 声明了一个名为hello 的方法,返回一个Class1 的对象。因此,从该方法返回的内容必须实现与Class1 的兼容接口。当Class1.hello() 返回Class2 的实例时,调用者与它的交互方式不应该与Class1 的实例不同——这是Liskov Substitution Principle 在行动中的一种——关键的面向对象原则。

    如果 Class2.hello() 由于 Class2 被隐藏而变得不可访问,那么调用者将不得不面对这样一个事实,即他们不知道 Class1.hello() 将返回什么类型的对象 - 有时它可能是Class2 的对象,有时它可能是 Class1 的对象,或任何其他可以从 Class1 扩展的对象,唯一的了解方法是检查代码 - 即了解 Class1 的实现细节.在这种情况下,编译器无法保证类型安全,因为Class1.hello() 原则上可能是不可判定的或依赖于运行时状态。使用一种静态类型的语言,游戏几乎结束了。

    以某种方式隐藏一个类——通过将其创建为私有类型、通过匿名实现接口、通过反射技巧等——只应该使类型本身隐藏而不是它实现的接口。通过扩展另一个类,任何给定类型都会自动继承父类型的接口,包括其可见性。扩展类型只允许增加接口的可见性,不能降低它,否则就违反了里氏替换原则。

    【讨论】:

      猜你喜欢
      • 2015-09-02
      • 1970-01-01
      • 2011-07-15
      • 2015-11-20
      • 1970-01-01
      • 2017-09-14
      • 2021-02-28
      • 2023-03-28
      相关资源
      最近更新 更多