Java面向對象三大特徵之一 —— 繼承的相關概念
(一)、概念
繼承
:就是子類繼承父類的屬性
和行爲
,使得子類對象具有與父類相同的屬性、相同的行爲。子類可以直接訪問父類中的非私有
的屬性和行爲.- 多個類可以稱爲子類,單獨那一個類稱爲父類、超類(superclass)或者基類。
- 繼承描述的是事物之間的所屬關係,這種關係是:is-a 的關係。
(二)、繼承的格式
- 通過
extends
關鍵字,可以聲明一個子類繼承另外一個父類,定義格式如下:
class 父類 {
...
}
class 子類 extends 父類 {
...
}
繼承演示,代碼如下:
/*定義員工類Employee,做爲父類*/
class Employee {
String name; // 定義name屬性
// 定義員工的工作方法
public void work() {
System.out.println("盡心盡力地工作");
}
}
/* 定義講師類Teacher 繼承 員工類Employee*/
class Teacher extends Employee {
// 定義一個打印name的方法
public void printName() {
System.out.println("name=" + name);
}
}
/* 定義測試類*/
public class ExtendDemo01 {
public static void main(String[] args) {
// 創建一個講師類對象
Teacher t = new Teacher();
// 爲該員工類的name屬性進行賦值
t.name = "小明";
// 調用該員工的printName()方法
t.printName(); // name = 小明
// 調用Teacher類繼承來的work()方法
t.work(); // 盡心盡力地工作
}
}
(三)、繼承後的特點——成員變量
3.1 成員變量重名
- 在父子類的繼承關係當中,如果成員變量重名,則創建子類對象時,訪問有兩種方式:
①、直接通過子類對象訪問成員變量:【等號左邊是誰,就優先用誰,沒有則向上找】。
class Fu {
// Fu中的成員變量。
int num = 5;
}
class Zi extends Fu {
// Zi中的成員變量
int num = 6;
public void show() {
// 訪問父類中的num
System.out.println("Fu num=" + num);
// 訪問子類中的num
System.out.println("Zi num=" + num);
}
}
class ExtendsDemo03 {
public static void main(String[] args) {
// 創建子類對象
Zi z = new Zi();
// 調用子類中的show方法
z.show();
}
}
演示結果:
Fu num = 6
Zi num = 6
3.2 區分子類方法中重名的三種
- 子父類中出現了同名的成員變量時,在子類中需要訪問父類中非私有成員變量時,需要使用
super
關鍵字,修飾父類成員變量。 - 使用格式:
super.父類成員變量名
class Zi extends Fu {
// Zi中的成員變量
int num = 6;
public void show() {
//訪問父類中的num
System.out.println("Fu num=" + super.num);
//訪問子類中的num
System.out.println("Zi num=" + this.num);
}
}
演示結果:
Fu num = 5
Zi num = 6
Fu 類中的成員變量是非私有的,子類中可以直接訪問。若Fu 類中的成員變量私有了,子類是不能
直接訪問的。通常編碼時,我們遵循封裝的原則,使用private修飾成員變量,那麼如何訪問父類的私有成員變量呢?對!可以在父類中提供公共的getXxx方法和setXxx方法。
②、通過間接的成員方法訪問成員變量:【該方法屬於誰,就優先用誰,沒有則向上找。】
class Fu {
int num = 100;
public void methodFu() {
//使用本類當中的,不會向下找子類的
System.out.println(num);
}
}
class Zi extends Fu {
int num = 200;
public void methodZi() {
//因爲本類當中有num,所以這裏使用的是本類的num
System.out.println(num);
}
}
class ExtendsDemo03 {
public static void main(String[] args) {
Fu fu = new Fu();
Zi zi = new Zi();
//這個方法是子類的,優先使用子類的,如果沒有再向上找
zi.methodZi();//200
//這個方法是在父類當中定義的
fu.methodFu();//100
}
}
(四)、成員方法重名——重寫(Override)
- 在父子類的繼承關係當中,創建子類對象,訪問方法的規則:【創建的對象是誰,就優先用誰,如果沒有則向上找。】
- 注意事項:無論是成員方法還是成員變量,如果沒有都是向上找父類,絕對不會向下找子類的。
class Fu {
public void methodFu() {
System.out.println("父類方法執行!");
}
public void method() {
System.out.println("父類重名方法執行!");
}
}
class Zi extends Fu{
public void methodZi() {
System.out.println("子類方法執行!");
}
public void method() {
System.out.println("子類重名方法執行!");
}
}
public class ExtendsDemo03{
public static void main(String[] args) {
Zi zi = new Zi();
zi.methodFu();
zi.methodZi();
//創建的是new了子類對象,所以優先使用子類方法
zi.method();
}
}
- 如果子類父類中出現重名的成員方法,這時的訪問是一種特殊情況,叫做方法重寫 (Override)。
方法重寫
:子類中出現與父類一模一樣的方法時(返回值類型,方法名和參數列表都相同),會出現覆蓋效果,也稱爲重寫或者複寫。聲明不變,重新實現
。
1.方法覆蓋重寫的注意事項:
- 必須保證父子類之間方法的名稱相同,參數也相同。@Override:寫在方法前面用來檢測是不是有效的正確覆蓋重寫。
- 子類方法的返回值必須【小於等於】父類方法的返回值範圍。注意:java.lang.Object類是所有類的公共最高父類,java.lang.String就是Object的子類。
- 子類方法的權限必須【大於等於】父類方法的權限修飾符。提示:public > protected > ( default) > private。備註:(default)不是關鍵字,而是什麼都不寫,留空。
2. 重寫的應用
子類可以根據需要,定義特定於自己的行爲。既沿襲了父類的功能名稱,又根據子類的需要重新實現父類方法,從而進行擴展增強。比如新的手機增加來電顯示頭像的功能,代碼如下
//本來的老款手機
class Phone {
public void call() {
System.out.println("打電話");
}
public void send() {
System.out.println("發短信");
}
public void show() {
System.out.println("顯示號碼");
}
}
//定義一個新的手機,使用老手機作爲父類
class NewPhone extends Phone {
@Override
public void show() {
super.show();// 把父類的show方法拿過來重複使用
// 自己子類再添加更多內容
System.out.println("顯示姓名");
System.out.println("顯示頭像");
}
}
public class Demo01Phone {
public static void main(String[] args) {
Phone phone = new Phone();
phone.call();
phone.send();
phone.show();
System.out.println("-----------");
NewPhone newPhone = new NewPhone();
newPhone.call();
newPhone.send();
newPhone.show();
}
}
運行結果:
打電話
發短信
顯示號碼
-----------
打電話
發短信
顯示號碼
顯示姓名
顯示頭像
這裏重寫時,用到super.父類成員方法,表示調用父類的成員方法
注意事項
①、 子類方法覆蓋父類方法,必須要保證權限大於等於父類權限。
②、 子類方法覆蓋父類方法,返回值類型、函數名和參數列表都要一模一樣。
(五)、繼承後的特點——構造方法
繼承關係中,父子類構造方法的訪問特點:
①、子類構造方法當中有一個默認隱含的" super() "調用,所以一定是先調用的父類構造,後執行的子類構造。
②、子類構造可以通過super關鍵字來調用父類重載構造。
③、super的父類構造調用,必須是子類構造方法的第一個語句。不能一個子類構造調用多次super構造。
總結:子類必須調用父類構造方法。不寫則贈送super():寫了則用寫的指定的super調用。super只能有一個,還必須是第一個。
class Fu{
public Fu() {
System.out.println("父類無參構造");
}
public Fu(int num) {
System.out.println("父類有參構造");
}
}
class Zi extends Fu{
public Zi() {
// super();//在調用父類無參構造方法
super(20);//在調用父類重載的構造方法
System.out.println("子類構造方法");
}
}
public class Demo01 {
public static void main(String[] args) {
Zi zi = new Zi();
}
}
(六)、 super和this
6.1 super關鍵字用來訪問父類的內容,用法有三種:
- 在子類的成員變量方法中,訪問父類的成員變量。
- 在子類的成員方法中,訪問父類的成員方法。
- 在子類的構造方法中,訪問父類的構造方法。
6.2 this關鍵字用來訪問本類內容,用法也有三種:
- 在本類的成員方法中,訪問本類的成員變量。
class Fu{
int num = 10;
}
class Zi extends Fu {
int num = 20;
System.out.print(num);//局部變量
System.out.print(this.num);//本類中的成員變量
System.out.print(super.num);//父類中的成員變量。
}
- 在本類的成員方法中,訪問本類的另一個成員方法。
public void methodA(){
System.out.print("AAA");
}
public void methodB(){
this.methodA();
System.out.print("BBB");
}
- 在本類的構造方法中,訪問本類的構造方法。
【在第三種用法當中要注意:
①、this(…)調用也必須是構造方法的第一個語句,唯一一個。
②、super和this兩種構造調用,不能同時使用。】
public Zi(){
this(123);//本類的無參構造,調用本類的有參構造
}
public Zi(int n){
}