问题一: "覆盖"私有方法
//: polymorphism/PrivateOverride.java
package polymorphism;
public class PrivateOverride {
private void func() {
System.out.println("private func()");
}
public static void main(String[] args) {
PrivateOverride po = new Derived();
po.func();
}
}
class Derived extends PrivateOverride {
public void func() {
System.out.println("public func()");
}
}
output:
我们期望输出的应该是public func(),但是由于private方法被自动认为是final方法,而且对于派生类是屏蔽的.因此,在这种情况下,Derived类中的func()方法就是一个全新的方法,基类中的func()方法在子类中Derived中不可见,因此甚至也不能被重载.
结论就是:只有非private方法才可以被覆盖.我们在Derived类中的func()方法前加一个@Override,然后进行编译
我们可以看到一个编译错误.这也证明了前面那句话.
所以,在派生类中,对于基类中的private方法,最好采用不同的名字.
问题二: 域与静态方法
我们可能会认为所有事物都可以多态的发生.然而,只有普通的方法调用可以是多态的.
如果你直接访问某个域,这个访问就将在编译期进行解析.
//: polymorphism/FieldAccess.java
package polymorphism;
class Super {
public int field = 0;
public int getField() {
return field;
}
}
class Sub extends Super {
public int field = 1;
@Override public int getField() {
return field;
}
public int getSuperField() {
return super.field;
}
}
public class FieldAccess {
public static void main(String[] args) {
Super sup = new Sub();
System.out.println("sup.field = " + sup.field + ", sup.getField() = " + sup.getField());
Sub sub = new Sub();
System.out.println("sub.field = " + sub.field + ", sub.getField() = " + sub.getField() +
", sub.getSuperField() = " + sub.getSuperField());
}
}
output:
当Sub对象转型为Super时,任何域访问操作都将由编译器解析,因此不是多态的.在本例中,为Super.field和Sub.field分配了不同的存储空间.这样,Sub中其实包含了两个称为field的域:它自己的和从Super中得到的.然后,在引用Sub中的field时所产生的默认域并非是Super版本的field域.因此,为了得到Super.field,必须显示的指明super.field.
当然,在实践中是不会写出这样的代码的.
如果某个方法是静态的,它的行为就不具有多态性.
//: polymorphism/StaticPolymorphism.java
package polymorphism;
class StaticSuper {
public static String staticGet() {
return "Base staticGet()";
}
public String dynamicGet() {
return "Base dynamicGet()";
}
}
class StaticSub extends StaticSuper {
public static String staticGet() {
return "Dervied staticGet()";
}
@Override
public String dynamicGet() {
return "Dervied dynamicGet()";
}
}
public class StaticPolymorphism {
public static void main(String[] args) {
StaticSuper sup = new StaticSub();
System.out.println(sup.staticGet());
System.out.println(sup.dynamicGet());
}
}
output:
我们可以看到staticGet()方法并没有被覆盖.
静态方法是与类,而并非与单个的对象相关联的.