1 目錄及資源索引
2 主要內容
本節課主要內容如下:
- 抽象函數的語法特徵;
- 抽象類的語法特徵;
- 抽象類的作用;
老師:“類是抽象的,對象是具體的;比類更具體的是抽象類;抽象的東西是有好處的,不容易錯。”
3 基本概念
3.1 抽象函數
什麼是抽象函數?
抽象函數,是用 abstract 修飾的函數;是隻有函數的定義,沒有函數體的函數。
例如:
abstract void fun();
代碼舉例如下:
class Person
{
String name;
int age;
void introduce()
{
System.out.println("我的名字是" + name + ",我的年齡是" + age);
}
abstract void eat(); // 抽象函數
}
上述代碼,編譯運行結果如下:
大概意思就是,裏邊定義了抽象函數,但是這個類不是一個抽象類,那什麼是抽象類呢?
3.2 抽象類
使用 abstract 定義的類就叫做抽象類;
抽象類有如下特徵:
- 抽象類不能夠生成對象;
- 如果一個類當中包含有抽象函數,那麼這個類必須被聲明爲抽象類;
- 如果一個類當中沒有抽象函數,那麼這個類也可以被聲明爲抽象類;
這個感覺跟C++中的虛函數有點像,父類中沒有函數體,是一個虛函數,需要子類中複寫。
另外需要注意的是:抽象類不能實例化對象, 否則意味着可以調用其中的抽象函數,而抽象函數是沒有函數體的。自己嘗試改了一下代碼,編譯後錯誤如下:
老師:“抽象類天生就是用來當爹的,天生就是用來當做父類的,子類可以實例化對象。”
哈哈,跟老師上課,老師的講課風格還是很幽默的。
如果子類直接繼承是抽象類的父類,如下直接寫是不可以的
class Chinese extends Person
{
}
編譯後,錯誤如下:
解決方法有兩個
- 把子類 Chinese 變成抽象類,但是需要注意抽象類不能實例化對象,看上圖下邊的錯誤;
- 第二種就是把父類的抽象函數複寫;
如果定義一個類,由於各種原因,不想讓他生成對象,就可以把它設置爲一個抽象類。
抽象類 基本等同於 基類,就是用來被繼承的類。
4 抽象類可以有構造函數嗎?
有兩個基本的概念:
- 抽象類不能生成對象;
- 構造函數用於生成類的對象;
看到上述兩個條件,可能很自然的就認爲抽象類沒有構造函數,下邊用代碼實際演示一下。
抽象類 Person 代碼如下:
abstract class Person
{
Person()
{
System.out.println("Person的構造函數!");
}
String name;
int age;
void introduce()
{
System.out.println("我的名字是" + name + ",我的年齡是" + age);
}
abstract void eat(); // 抽象函數
}
子類 Chinese 代碼如下:
class Chinese extends Person
{
Chinese()
{
System.out.println("Chinese的構造函數");
}
void eat()
{
System.out.println("用筷子喫飯");
}
}
存放主函數的類 Test,代碼如下:
class Test
{
public static void main(String args[])
{
// Person p = new Person();
// p.introduce();
Chinese c = new Chinese();
Person p = c; // 向上轉型
p.eat();
}
}
上述代碼編譯運行結果如下:
由上圖可得答案是:抽象類也是有構造函數的,爲子類調用的時候,做準備。
老師:“生成子類的時候,一定會先調用父類的構造函數。”
自我理解:之前課上講過,所有的類都有構造函數,就算不寫,編譯器也會默認創建一個。如果此處抽象類沒有構造函數,那就和這個結論相悖。
5 總結
- 抽象函數就是沒有函數體的函數;
- 抽象類使用 abstract 來定義;
- 抽象類不能生成對象,但是卻可以擁有構造函數。
- 抽象函數,抽象類的出現,爲子類繼承提供了很大的方便,相當於有了一個頂層框架;