第七講 繼承與多態
1.
源碼:
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();
}
}
運行結果:
修改之前:
修改之後:
在java語言的繼承中,在執行子類的構造方法之前,會先調用父類沒有參數的構造方法,其目的是為了要幫助繼承自父類的成員做初始化操作。子類的構造方法通過super()來調用父類特定的構造方法(如果沒有super語句還是會自動調用父類沒有參數的構造方法),調用父類特定的構造方法的super語句必須寫在子類構造方法的第一行,否則編譯時出錯,如果父類只定義了有參數的構造方法,而在子類中又沒有用super關鍵字來調用父類的特定構造方法,則編譯時出錯。
又問:
子類是通過父類繼承過來的,所以子類有父類的所有非私有的屬性和方法,如果不調用父類的構造方法,那麽不能初始化父類中定義的屬性,就給父類的屬性分配內存空間 ,如果父類的屬性沒有分配內存空間,那麽子類訪問父類的屬性,就會報錯。
2.
自行編寫代碼測試以下特性(動手動腦):
在子類中,若要調用父類中被覆蓋的方法,可以使用super關鍵字。
(1)覆蓋方法的允許訪問範圍不能小於原方法。
(2)覆蓋方法所拋出的異常不能比原方法更多。
(3)聲明為final方法不允許覆蓋。
例如,Object的getClass()方法不能覆蓋。
(4)不能覆蓋靜態方法。
3.
m=d; //編譯正確,因為子類對象可以直接賦給基類變量。
d=m; //編譯錯誤,基類對象要賦給子類對象變量,必須執行類型轉換(子類對象變量=(子類名)基類對象名;)
d=(Dog)m; //編譯正確,基類對象要賦給子類對象變量,必須執行類型轉換
d=c; //編譯錯誤,不同子類之間不能復制
c=(Cat)m; //m已經轉換成Dog, Dog和Cat子類之間不能轉換
4.
(1)運行結果:
(2)解釋:
在調用的時候,對象是子類的,就調用子類的方法,對象是父類的,就調用父類的方法。父類對象訪問子類成員,調用相同的函數名的函數屬於子類的;父類的變量進行相關的原算,但是,如果這時父類變量指向子類對象,繼續調用得方法和變量仍然是子類覆蓋後的新的變量和方法的,例如如果將代碼改為:
則第三個結果為:101
最後一個輸出為父類強轉為子類對象,調用的是子類的變量和方法輸出。
(3)
父類對象可以訪問子類的成員,當然只限於”覆蓋”發生時,調用的時候,對象是子類的,就調用子類的方法,對象是父類的,就調用父類的方法。當然還有如下特性:
1.當子類與父類擁有一樣的方法,並且讓一個父類變量引用一個子類對象時,到底調用哪個方法,由對象自己的“真實”類型所決定,這就是說:對象是子類型的,它就調用子類型的方法,是父類型的,它就調用父類型的方法。這個特性實際上就是面向對象“多態”特性的具體表現。
2.如果子類與父類有相同的字段,則子類中的字段會代替或隱藏父類的字段,子類方法中訪問的是子類中的字段(而不是父類中的字段)。如果子類方法確實想訪問父類中被隱藏的同名字段,可以用super關鍵字來訪問它。
3.如果子類被當作父類使用,則通過子類訪問的字段是父類的.
5.
源碼:
class Parent
{
public int value=100;
public void Introduce()
{
System.out.println("I‘m father");
}
}
class Son extends Parent
{
public int value=101;
public void Introduce()
{
System.out.println("I‘m son");
}
}
class Daughter extends Parent
{
public int value=102;
public void Introduce()
{
System.out.println("I‘m daughter");
}
}
public class TestPolymorphism
{
public static void main(String args[])
{
Parent p=new Parent();
p.Introduce();
System.out.println(p.value);
p=new Son();
p.Introduce();
System.out.println(p.value);
p=new Daughter();
p.Introduce();
System.out.println(p.value);
}
}
結果:
多態依賴於類型和實現的分離,多用來把接口和實現分離。
6.(多態:多態性(polymorphisn)是允許你將父對象設置成為和一個或更多的他的子對象相等的技術,賦值之後,父對象就可以根據當前賦值給它的子對象的特性以不同的方式運作。簡單的說,就是一句話:允許將子類類型的指針賦值給父類類型的指針。)
運行結果如:
雖然猴子和鴿子有數量的變化,定義固定長度的數組使用不方便,長度有限。
(接口)固定數組實現
public class Denglu
{
public static void main(String args[])
{
Feeder f = new Feeder("小李");
// 飼養員小李餵養一只獅子
f.eat();
// 飼養員小李餵養十只猴子
for (int i = 0; i < 10; i++)
{
f.eat1();
}
// 飼養員小李餵養5只鴿子
for (int i = 0; i < 5; i++)
{
f.eat3();
}
}
}
interface Lion
{
abstract void eat();
}
interface Monkey
{
abstract void eat1() ;
}
interface Pigeon extends Lion,Monkey
{
abstract void eat3() ;
}
class Feeder implements Pigeon
{
public String name;
public Feeder(String name)
{
this.name = name;
}
public void eat()
{
System.out.println("我不吃肉誰敢吃肉!");
}
public void eat1()
{
System.out.println("我什麽都吃,尤其喜歡香蕉。");
}
public void eat3()
{
System.out.println("我要減肥,所以每天只吃一點大米。");
}
}
運行結果:
第七講 繼承與多態