【问题标题】:Inheritance: weaker accessibility of a method in subclass继承:子类中方法的可访问性较弱
【发布时间】:2014-05-27 19:01:21
【问题描述】:

在 java 中有什么需要这样的规则:

“子类不能削弱父类中定义的方法的可访问性”

【问题讨论】:

    标签: java inheritance subclass superclass


    【解决方案1】:
    class Person {
        public String name() {
            return "rambo";
        }
    }
    
    // subclass reduces visibility to private
    class AnonymousPerson {
        private String name() {
            return "anonymous";
        }
    }
    

    使用PersonAnonymousPerson 作为参数调用以下方法是合法的。但是,如果方法的可见性受到限制,它就无法调用name() 方法。

    class Tester {
        static void printPersonName(Person p) {
            System.out.println(p.name());
        }
    }
    
    //ok
    Tester.printPersonName(new Person());
    

    这个调用是合法的,因为PersonAnonymousPerson,但它必须在方法体内失败。这违反了“类型安全”。

    Tester.printPersonName(new AnonymousPerson());
    

    【讨论】:

      【解决方案2】:

      含义

      子类方法的可见性不能比超类方法更严格。

      例如,如果定义了超类

      protected void a() { } // visible to package and subclasses
      

      子类可以用其中之一覆盖它

      public void a() { }    // visible to all
      protected void a() { } // visible to package and subclasses
      

      但不是

      void a() { }           // visible to package
      private void a() { }   // visible to itself
      

      为什么

      假设定义是

      class A {
          public void a() { }
      }
      
      class B extends A {
          private void a() { }
      }
      

      现在,考虑下面的代码

      A instance = new B();
      instance.a(); // what does this call? 
      

      一方面,任何B 都有一个可公开访问的a 方法。另一方面,B 实例的a 方法只能由B 访问。


      更一般地说,子类(接口)必须履行其超类(接口)的契约。

      可见性只是这一原则的一个例子。另一个例子是非抽象类必须实现它实现的任何接口的所有方法。

      【讨论】:

      • 我不是在问意义。我在问为什么我们需要这样的规则?
      【解决方案3】:

      如果你有一个带有公共方法的类

      public class Foo {
          public void method() {}
      }
      

      此方法是可访问的,因此您可以这样做

      Foo foo = new Foo();
      foo.method();
      

      如果你添加一个子类

      public class Bar extends Foo {
          @Override
          public /* private */ void method() {}
      }
      

      如果是private,你应该做不到

      Foo bar = new Bar();
      bar.method();
      

      在此示例中,BarFoo,因此它必须能够替换 Foo 任何需要的位置。

      为了满足上述陈述,子类不能使可继承成员的可访问性降低。但是,它可以使其更易于访问。 (这基本上只适用于方法。)

      【讨论】:

        【解决方案4】:

        履行接口契约。假设我有一个接口,IFlying,如下:

        public interface IFlying {
            public void fly();
        }
        

        我有一个削弱可访问性的实现:

        public class Bird implements IFlying {
            private void fly(){
                System.out.println("flap flap");
            }
        }
        

        我现在有一些接受 IFlying 的库函数,并在其上调用 fly。实现是私有的。现在会发生什么?当然,这意味着fly方法无法访问。

        因此,可访问性在实现中可能不会受到更多限制。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-12-13
          • 2021-06-29
          • 1970-01-01
          • 2021-05-07
          • 2017-07-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多