【问题标题】:Private methods in Inheritance继承中的私有方法
【发布时间】:2013-01-01 18:11:08
【问题描述】:

这是一段有趣的代码sn-p:

public class Superclass {

    public static void main (String[] args){
        Superclass obj = new Subclass();
        obj.doSomething(); #prints "from Superclass"
    }

    private void doSomething(){System.out.println("from Superclass");}
}

class Subclass extends Superclass {

    private void doSomething(){System.out.println("from Subclass");}

}

我知道子类不会继承其父类的私有成员,但这里 obj 设法调用了它不应访问的方法。在编译时 obj 是 Superclass 类型,在运行时是 Subclass 类型。

这可能与对 doSomething() 的调用发生在驱动程序类内部这一事实有关,该驱动程序类恰好是它自己的类(以及为什么可以首先调用 doSomething() 的原因)。

所以问题归结为,obj 如何访问其父级的私有成员?

【问题讨论】:

  • 看看子方法公开时会发生什么会很有趣。我已经做到了,它说:“来自超类” 有趣,它不会覆盖它

标签: java inheritance private


【解决方案1】:
Superclass obj = new Subclass();

此时,obj 是两个东西,一个 Subclass 和一个 Superclass 对象。在变量声明中使用Superclass 的事实只是转换它的问题。

当您这样做时:obj.doSomething(),您是在告诉编译器调用 obj 的私有方法 doSomething()。因为您是从Superclass 中的主要静态方法执行的,所以编译器可以调用它。

如果您使用Subclass 的主要方法而不是Superclass 中的那个方法,您将无法访问该方法,因为正如您所说,它既不是继承的,也不是您对@987654332 的定义的一部分@。

所以基本上你正确理解了继承。问题与私有方法的可见性有关。

【讨论】:

    【解决方案2】:

    为什么首先可以调用 doSomething()?

    为什么不呢? objSubclassSuperclass 的实例,由于doSomething()Superclass 中声明,obj 在其中使用,所以您可以访问Superclass.doSomething(),您可以尝试重命名您的方法(egdoAnotherThing()),您仍然可以访问它。

    obj 如何访问其父级的私有成员?

    私有方法没有父/子,由于obj也是Superclass的一种类型,所以它可以访问其中声明的所有私有方法/字段,因为obj在此使用班级。如果您不在Superclass 或以Superclass 作为成员的类(嵌套类)之外,您将失去此访问权限。

    那又怎样?

    SuperClass 的私有方法和SubClass 的私有方法之间没有关系/继承关系,即使它们具有相同的名称和签名,来自Java Language Specification, Java SE 8 Edition

    私有方法和在 final 中立即声明的所有方法 类(§8.1.1.2)表现得好像它们是最终的,因为这是不可能的 覆盖它们。

    【讨论】:

      【解决方案3】:

      要理解这个问题,您可以将私有方法与超类和子类的成员变量联系起来。

      所以我们知道成员变量不会在子类中被覆盖。

      例如:

      Class A{
       int i = 10;
      }
      
      Class B extends A{
        int i = 11;
      }
      
      Class C extends A {
         int i = 12;
      }
      
      A a1 = new B();
      print(a1.i) // Will print 10
      
      A a2 = new B();
      print(a2.i) // Will print 10 
      

      不考虑继承引用变量超类时的类似方式。

      【讨论】:

      • 你想通过显示最后两行代码来说明什么?它们与前面的行不完全相同吗?
      • 是的,它们是相同的..只是我给出了两个子类而不是一个..我认为一个应该没问题。
      【解决方案4】:

      当我们在派生类中定义一个同名的私有方法时,它成为一个新方法,因为派生类不继承私有成员。

      由于私有方法在类外是不可见的,我们永远不能从派生类调用基类私有方法,它会抛出编译错误:

      线程“main”java.lang.Error 中的异常:未解决的编译问题: Base 类型的方法 aPrivateMethod() 不可见

      我们可以使用向下转换到父类引用来调用派生类的私有方法,该方法只能在该派生类中访问。

      【讨论】:

        【解决方案5】:

        由于对象obj 的引用类型是SuperClass,因此对doSomething() 的调用会尝试访问在SuperClass 本身中定义的私有方法(私有方法不能被覆盖)。 由于doSomething() 可以在SuperClass 中访问,所以main 方法可以调用doSomething() 而不会出现任何错误。

        希望这会有所帮助! :-)

        【讨论】:

          【解决方案6】:

          之所以有效,是因为您正在从Superclass 的方法中强制转换为Superclass。在这种情况下,Superclass.doSomething 可供编译器使用。

          如果您要将超类和子类更改为两个不同的任意类 A 和 B,与包含 main 方法的类无关,并尝试相同的代码,编译器会抱怨无法访问该方法.

          【讨论】:

            【解决方案7】:

            私有方法仅供所有者使用。

            即使是主人的孩子、亲戚或朋友也不行。

            【讨论】:

              【解决方案8】:

              当你使用这条线时:

              Superclass obj = new Subclass();
              

              您将 Subclass 转换为 Superclass Object,它仅使用 Superclass 的方法和相同的数据。如果你将它转换回子类,你可以再次使用子类方法,如下所示:

              ((Subclass)obj).doSomething(); #prints "from Subclass"
              

              【讨论】:

              • 给定 OP 代码,((Subclass)obj).doSomething(); #prints "from Subclass" 将无法编译,因为您正在访问其类 Subclass 之外的 private 方法。
              【解决方案9】:

              你自己回答了。由于私有方法不被继承,超类引用调用它自己的私有方法。

              【讨论】:

              • 如果“引用”是指存储在变量 obj 中的指针所引用的子类实例,这是一个循环答案。该实例仍然是 Subclass 类型,它不应该访问父级的私有成员。
              • 重点是您将其分配给超类引用。并且由于该方法是私有的,它不会被子类实现覆盖。该引用只知道一个 doSomething 方法,它位于超类中。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2015-03-19
              • 1970-01-01
              • 2019-02-10
              • 1970-01-01
              • 2014-11-24
              • 2013-12-14
              相关资源
              最近更新 更多