請看如下「變態」的類spa
ParentChildTest.Java示例 對象
public class ParentChildTest {blog
public static void main(String[] args) {繼承
Parent parent=new Parent();開發
parent.printValue();博客
Child child=new Child();class
child.printValue();變量
parent=child;語法
parent.printValue();引用
parent.myValue++;
parent.printValue();
((Child)parent).myValue++;//
parent.printValue();
}
}
class Parent{
public int myValue=100;
public void printValue() {
System.out.println("Parent.printValue(),myValue="+myValue);
}
}
class Child extends Parent{
public int myValue=200;
public void printValue() {
System.out.println("Child.printValue(),myValue="+myValue);
}
}
1. 程序運行結果是什麼? 2. 你如何解釋會獲得這樣的輸出? 3. 計算機是不會出錯的,之因此獲得這樣的運行結果也是有緣由的,那麼從這些運行結果中,你能總結出Java的哪些語法特性?
程序運行結果:
解釋:
父類對象被定義成子類類型(家族的具體化)
既然子類繼承父類,因此子類更能表明這一個家族的具體表現,一個父類的對象被定義成子類類型時就具備了父類的屬性和方法。
反過來子類對象不能被定義成父類類型
子類對象爲何不能被定義成父類類型呢?由於子類繼承於父類,所以子類擁有的方法極可能比父類多,由於除了繼承自父類的所有屬性和方法外,子類有可能定義了其餘的方法,因此大致上看子類的量級要比父類大,因此父類對象能夠定義成子類對象,由於多出來的方法能夠直接使用子類的,而反過來的話就不行了,由於子類對象不知道如何砍掉那些多出來的方法。
因此,一句話就是小盒子(父類對象)能夠套進大盒子(子類)裏,大盒子(子類對象)不能套進小盒子(父類)裏。
同理,父類對象能夠被子類對象賦值(被定義成子類類型),子類對象不能被父類對象賦值。
父類對象只有當明確轉換爲子類對象時才能夠直接控制對象中的屬性,只是經過賦值來使父類對象變成子類類型的辦法不能使父類對象徹底控制對象中的屬性。
若是子類與父類有相同的字段,則子類中的字段會代替或隱藏父類的字段,子類方法中訪問的是子類中的字段(而不是父類中的字段)。
換言之,一旦子類父類具備相同名稱的字段,就會使繼承的狀況變得複雜,子類中的父類同名變量或方法就會褪色而不易被調用。
好比,父類子類都有名爲F的屬性或方法,那麼在繼承時,子類就會有兩個F屬性或方法,一個繼承於父類(由父類定義),而另外一個由子類本身定義。生成一個子類對象時,子類對象一旦調用F屬性或執行F方法就會優先使用子類本身的F屬性或執行子類本身的F方法,若是要強行使用父類的F屬性或執行父類F方法,得在子類定義中使用super.F()來調用。
總結:(1)當子類與父類擁有同樣的方法,而且讓一個父類變量引用一個子類對象時,到底調用哪一個方法,由對象本身的「真實」類型所決定,這就是說:對象是子類型的,它就調用子類型的方法,是父類型的,它就調用父類型的方法。
這個特性實際上就是面向對象「多態」特性的具體表現。
(2)若是子類與父類有相同的字段,則子類中的字段會代替或隱藏父類的字段,子類方法中訪問的是子類中的字段(而不是父類中的字段)。若是子類方法確實想訪問父類中被隱藏的同名字段,能夠用super關鍵字來訪問它。若是子類被看成父類使用,則經過子類訪問的字段是父類的!牢記:(驗證結論發博客) 在實際開發中,要避免在子類中定義與父類同名的字段。不要自找麻煩!——但考試除外,考試中出這種題仍是能夠的。