8
package P1;

public class Base {

   private void pri( ) { System.out.println("Base.pri()");  }

   void pac( ) {  System.out.println("Base.pac()");  }

   protected void pro( ) { System.out.println("Base.pro()"); }

   public void pub( ) { System.out.println("Base.pub()"); }

   public final void show( ) {
       pri();  
       pac();  
       pro();  
       pub(); 
   }    
} 

package P2;

import P1.Base;

public class Concrete1 extends Base {
   public void pri( ) { System.out.println("Concrete1.pri()"); }
   public void pac( ) { System.out.println("Concrete1.pac()"); }
   public void pro( ) { System.out.println("Concrete1.pro()"); }
   public void pub( ) { System.out.println("Concrete1.pub()"); }
}

我正在执行

Concrete1 c1 = new Concrete1();
c1.show( );

现在,输出显示为

Base.pri()
Base.pac()
Concrete1.pro()
Concrete1.pub()

有人可以解释为什么会这样吗?根据我对继承的理解,这应该发生:

1)P2.concrete1 继承 P1.Base
2)concrete1 的 c1 对象被创建
3)c1.show()被调用。由于 P1.Base.show() 是public,所以可以调用它。
4) 现在,在继承后的P2.concrete1中,只能访问它自己的方法(pri、pac、pro、pub)和P1.Base的可继承方法(pro、pub、show)。

现在为什么它甚至无法访问时在输出中显示 Base.pri() 和 Base.pac() ?

很明显,我对继承没有非常清楚的基本理解。有人可以解释这种情况以及继承实际上是如何“结构化”的。我曾经认为超类的可继承方法和字段只会叠加到子类上。但这种推理显然是错误的。

谢谢!

4

2 回答 2

12

简短的回答是您只能覆盖可见的方法。前两种方法,pri分别pac私有的和包保护的。因为类之外的任何东西都不能看到私有方法,所以它不能被覆盖。同样,因为Concrete1它在不同的包中,Base所以它看不到Base.pac,所以不能覆盖它。

这意味着当您在 中定义 apripac方法时Concrete1,它们只是恰好与 中的方法具有相同名称的方法Base,而不是覆盖。其他两种方法propub分别是受保护的和公共的,因此对Concrete1. 因此 in 中的propub方法是对 inConcrete1中同名方法的覆盖Base

因为show在 中定义Base,所以它是调用 4 中定义的方法进行编译的Base。执行时,JVM 会查看是否有任何被覆盖以及是否执行被覆盖的方法。如上所述,pri并且pac没有被覆盖,因此版本在Base原样执行的地方执行。propubConcrete1

如果您将该show方法移入Concrete1而不是Basethen ,它将执行 4 中定义的方法,Concrete1因为这些方法对show.

于 2012-09-15T04:12:06.760 回答
0

私有和无修饰符方法在设计上对其子类不可见。有关详细说明,请参见此处

于 2012-09-15T04:16:00.687 回答