繼承的好處
1. 提高了代碼的複用性。
2. 讓類與類之間産生了關系,給第三個特征多态提供了前提。
java中支援單繼承,不直接支援多繼承,但對C++中的多繼承機制進行改良。
java支援多層繼承。
C繼承B,B繼承A,就會出現繼承體系。
當要使用一個繼承體系時:
1. 檢視該體系中的頂層類,了解該體系的基本功能。
2. 建立體系中的最子類對象,完成共能的使用。
什麼時候定義繼承呢?
當類與類之間存在着所屬關系的時候,就定義繼承,xxx是yyy中的一種, xxx extends yyy。
class Person
{
String name;
int age;
}
class Student extends Person //繼承
{
// String name;
// int age;
void study()
{
System.out.println(name+"...student study...."+age);
}
}
class Worker extends Person
{
// String name;
// int age;
void work()
{
System.out.println("worker work");
}
}
class ExtendsDemo
{
public static void main(String[] args)
{
Student s = new Student();
s.name = "zhangsan";
s.age = 20;
s.study();
}
}
在子父類中,成員的特點展現
1.成員變量
2.成員函數
3.構造函數
1. 成員變量
當本類的成員和局部變量同名時,用this區分;
當子父類中的成員變量同名時,用super區分父類。
this和super的用法很相似。
this:代表一個本類對象的引用。
super:代表一個父類的空間,并不代表父類對象。
class Fu
{
int num = 4;
}
class Zi extends Fu
{
int num = 5;
void show()
{
System.out.println(super.num+"..."+num);
}
}
class ExtendsDemo2
{
public static void main(String[] args)
{
Zi z = new Zi();
z.show();
}
}
2. 成員函數
當子父類中出現成員函數一模一樣的情況,會運作子類的函數。
這種現象,稱為覆寫操作,這時函數在子父類中的特性。
函數兩個特性:
1.重載. 同一個類中,overload
2.覆寫. 子類中,覆寫也稱為重寫,override
覆寫注意事項:
1.子類方法覆寫父類方法時,子類權限必須要大于等于父類的權限。
2.靜态隻能覆寫靜态,或被靜态覆寫。
class Fu
{
void show()
{
System.out.println("fu show run");
}
}
class Zi extends Fu
{
void show()
{
System.out.println("zi show run");
}
}
class ExtendsDemo2
{
public static void main(String[] args)
{
Zi z = new Zi();
z.show();
}
}
什麼時候使用覆寫?
當對一個類進行子類的擴充時,子類需要保留父類的功能聲明。
但是要定義子類中該功能的特有内容時,就是用覆寫操作完成。
class Phone
{
void call()
{}
void show()
{
// System.out.println("pic");
// System.out.println("name");
System.out.println("number");
}
}
應用場景
現在手機更新了,加了顯示姓名和圖檔的功能。
但是如果我直接在源代碼上修改會增加修改成本,不好。
這時候我們就可以用繼承來解決。
class NewPhone extends Phone
{
void show()
{
System.out.println("pic");
System.out.println("name");
// System.out.println("number");
super.show();
}
}
class PhoneDemo
{
public static void main(String[] args)
{
// Phone p = new Phone();
// p.show();
NewPhone p = new NewPhone();
p.show();
}
}
子父類中構造函數的繼承
在子類構造對象時,發現通路子類構造函數時,父類也運作了。
為什麼呢?
原因是:在子類的構造函數中第一行有一個預設的隐式語句---super();
子類的執行個體化過程:子類中所有的構造函數預設都會通路父類中的空參數的構造函數。
class Fu
{
Fu()
{
System.out.println("fu run");
}
}
class Zi extends Fu
{
Zi()
{
//super(); //預設的隐式語句. 調用的就是父類中的空參數的構造函數.
System.out.println("zi run");
}
}
class ExtendsDemo4
{
public static void main(String[] args)
{
new Zi();
/*
結果為:
fu run
zi run
*/
}
}
還有一種情況
class Fu
{
Fu()
{
System.out.println("fu run");
}
Fu(int x)
{
System.out.println("fu run...."+x);
}
}
class Zi extends Fu
{
Zi()
{
//super(); //預設的隐式語句. 調用的就是父類中的空參數的構造函數.
System.out.println("zi run...");
}
Zi(int x)
{
System.out.println("zi run...."+x);
}
}
class ExtendsDemo4
{
public static void main(String[] args)
{
new Zi(4);
/*
結果為:
fu run
zi run....4
*/
}
}
為什麼子類執行個體化的時候要通路父類中的構造函數呢?
那是因為子類繼承了父類,擷取到了父類中的内容(屬性),是以在使用父類内容之前,要先看父類是如何對自己的内容進行初始化的。
是以子類在構造對象時,必須通路父類中的構造函數。
為什麼完成這個必須的動作,就子啊子類的構造函數中加了super(). 語句。
如果父類中沒有定義空參數構造函數,那麼子類的構造函數必須用super明确要調用父類中哪個構造函數。
同時子類構造函數中如果使用this調用了本類構造函數時,
那麼super就沒有了,因為super和this都隻能定義第一行.是以隻能有一個。
但是可以保證的是,子類中肯定會有其他的構造函數通路父類的構造函數。
注意:super語句必須要定義在子類構造函數的第一行,因為父類的初始化動作要先完成。
class Fu
{
Fu()
{
super();
show();
return;
}
void show()
{
System.out.println("fu show");
}
}
class Zi extends Fu
{
int num = 8;
Zi()
{
//super(); //預設的隐式語句. 調用的就是父類中的空參數的構造函數.
//-->通過super初始化父類内容時,子類的成員變量并未顯示初始化.
//等super()父類初始化完畢後,才進行子類的成員變量顯示初始化.
//也就是說要先忙完父類那邊的事,然後才能忙自己的事.
System.out.println("zi cons run..."+num);
}
void show()
{
System.out.println("zi show ..."+num);
}
}
class ExtendsDemo5
{
public static void main(String[] args)
{
Zi z = new Zi();
z.show();
/*
結果為:
zi show...0
zi cons run...8
zi show...8
*/
}
}
一個對象執行個體化的過程:
Person p = new Person();
1. jvm會去讀取指定路徑下的Person.class檔案,并加載進記憶體。
并會先加載Person的父類(如果有直接的父類的情況下)。
2. 在堆記憶體中的開辟空間,配置設定位址。
3. 并在對象空間中,對對象中的屬性進行預設初始化。
4. 調用對應的構造函數進行初始化。
5. 在構造函數中,第一行會先調用父類中的構造函數進行初始化。
6. 父類初始化完畢後,再對子類的屬性進行顯示初始化。
7. 在進行子類構造函數的特定初始化。
8. 初始化完畢後,将位址指派給引用變量。
我是Vector,謝謝關注。