繼承與多態
1. 觀察輸出,註意總結父類與子類之間構造方法的調用關系修改Parent構造方法的代碼,顯式調用GrandParent的另一個構造函數,註意這句調用代碼是否是第一句,影響重大!
class Grandparent { public Grandparent() { System.out.println("GrandParent Created."); } public Grandparent(String string) { System.out.println("GrandParent Created.String:" + string); } }class Parent extends Grandparent { public Parent() { super("Hello.Grandparent."); System.out.println("Parent Created"); // super("Hello.Grandparent."); } } class Child extends Parent { public Child() { System.out.println("Child Created"); } }public class TestInherits { public static void main(String args[]) { Child c = new Child(); } }
通過 super 調用基類構造方法,必須是子類構造方法中的第一個語句。
2.現在有三個類:
class Mammal{}
class Dog extends Mammal {}
class Cat extends Mammal{}
針對每個類定義三個變量並進行初始化
Mammal m=null ;
Dog d=new Dog();
Cat c=new Cat();
下列語句哪一個將引起編譯錯誤?為什麽?哪一個會引起運行時錯誤?為什麽?
m=d;
d=m;
d=(Dog)m;
d=c;
c=(Cat)m;
猜想:第二句將引起編譯錯誤,因為將基類轉化為子類需要強制類型轉換、子類有的基類不一定有;第四句會引起編譯時的錯誤,因為d,c不是同一個類的對象。不知那一句會在運行時出錯
運行後:最後一句在運行時出錯,因為第一句將Dog類對象賦給Mammal對象m,再將m賦給c,就相當於將d賦給c,不同子類會出錯。
3.
public class ParentChildTest { public static void main(String[] args) { Parent parent=new Parent(); parent.printValue(); Child child=new Child(); 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); } }
(2) 你如何解釋會得到這樣的輸出?
當子類與父類擁有一樣的方法,並且讓一個父類變量引用一個子類對象時,到底調用哪個方法,由對象自己的“真實”類型所決定,這就是說:對象是子類型的,它就調用子類型的方法,是父類型的,它就調用父類型的方法。如果子類與父類有相同的字段,則子類中的字段會代替或隱藏父類的字段,子類方法中訪問的是子類中的字段(而不是父類中的字段)。如果子類方法確實想訪問父類中被隱藏的同名字段,可以用super關鍵字來訪問它。
如果子類被當作父類使用,則通過子類訪問的字段是父類的!
繼承與多態