Java 面向?qū)ο?繼承

1.繼承的概述

泛指把前人的作風(fēng)、文化、知識、財產(chǎn)等接受過來

java中的繼承

讓類與類之間產(chǎn)生父子關(guān)系

被繼承的類叫做父類(基類、超類)

繼承的類叫做子類(派生類)

格式(extends)

class 父類{

//.....

}

class 子類 extends 父類{

//.....

}

子類繼承父類之后有什么效果

子類可以使用父類中的非私有成員(成員變量、成員方法)

例子:

//定義父類Parent

public class Parent {

??? //成員變量

? ? private Stringname;

??? private? int age;

??? //公共訪問方式

? ? //快捷鍵: alt + insert 快速創(chuàng)建 getXXX(), setXXX()和構(gòu)造方法

? ? public void setName(String name) {

??? ??? this.name = name;

}

??? public String getName() {

??? ??? return name;

??? }

public void setAge(int age) {

??? ??? ??? this.age = age;

??? }

??? public int getAge() {

??? ??? return age;

??? }

??? //構(gòu)造方法

? ? //無參構(gòu)造

? ? public Parent() {

??? }

??? //全參構(gòu)造

? ? public Parent(String name,int age) {

??? ??? this.name = name;

??? ??? this.age = age;

??? }

}

//定義一個子類 Child 繼承 父類Parent

public class Childextends Parent {

}

//測試類

public class Test {

??? //main函數(shù)是程序的主入口,所有的代碼都是從這里開始

? ? public static void main(String[] args) {

??? ??? //1.創(chuàng)建一個子類對象

? ? ? ? Child child =new Child();

??? ??? //2.給對象的成員變量賦值

? ? ? ? child.setName("張三");

??? ??? child.setAge(12);

??? ??? //3.打印對象成員變量

? ? ? ? System.out.println("姓名:"+child.getName()+"年齡:"+child.getAge());

??? ??? /*

? ? ? ? ? ? 子類可以使用父類中的非私有成員(成員變量、成員方法)*/

? ? }

}

運行結(jié)果:


2.繼承的使用場景

·多個類中存再相同的屬性和行為時,可以將這些內(nèi)容提取出來放到一個新類中,讓這些類和新類產(chǎn)生父子關(guān)系,實現(xiàn)代碼復(fù)用

例子:定義繼承關(guān)系的動物類并使用

需求:分別定義Dog類,Pig類,它們共有屬性:name、age、sex,共有的行為有:eat(),兩者特別的行為時:watch(),snore()

//定義一個父類 Animal 動物類

public class Animal {

??? //成員變量

? ? //姓名

? ? private Stringname;

??? //年齡

? ? private int age;

??? //性別

? ? private Stringsex;

??? //成員方法

? ? //吃飯行為

? ? public void eat(){

??? ??? System.out.println(this.name+"正在吃飯....");

??? }

??? //公共訪問方法

? ? public void setName(String name) {

??? ??? this.name = name;

??? }

??? public void setAge(int age) {

??? ??? this.age = age;

??? }

??? public void setSex(String sex) {

??? ??? this.sex = sex;

??? }

??? public String getName() {

??? ??? return name;

??? }

??? public int getAge() {

??? ??? return age;

??? }

??? public String getSex() {

??? ??? return sex;

??? }

??? //構(gòu)造方法

? ? //無參構(gòu)造

? ? public Animal() {

??? }

??? //全參構(gòu)造

? ? public Animal(String name,int age, String sex) {

??? ??? this.name = name;

??? ??? this.age = age;

??? ??? this.sex = sex;

??? }

}

//定義一個子類 Dog 繼承父類Animal

public class Dogextends Animal{

??? //成員方法

? ? public void watch(){

??? ??? System.out.println(this.getName()+"正在看家");

??? }

}

//定義一個子類 Pig 繼承父類 Animal

public class Pigextends Animal {

??? //成員方法

? ? public void snore(){

??? ??? System.out.println(this.getName()+"正在打鼾");

??? }

}

//測試類

public class Test {

??? public static void main(String[] args) {

??? ??? //1.創(chuàng)建一個Dog類的對象

? ? ? ? Dog dog =new Dog();

??? ??? //2.給dog對象成員對象賦值

? ? ? ? dog.setName("哈士奇");

??? ??? //3.打印dog對象的成員變量

? ? ? ? System.out.println("姓名:"+dog.getName());

??? ??? //4.調(diào)用dog對象的方法

? ? ? ? dog.eat();

??? ??? dog.watch();

??? ??? System.out.println("============");

??? ??? //1.創(chuàng)建一個pig類的對象

? ? ? ? Pig pig =new Pig();

??? ??? //2.給pig對象成員變量賦值

? ? ? ? pig.setName("荷蘭豬");

??? ??? //3.打印pig對象的成員變量

? ? ? ? System.out.println("姓名:"+pig.getName());

??? ??? //調(diào)用pig對象的成員方法

? ? ? ? pig.eat();

??? ??? pig.snore();

??? }

}

運行結(jié)果:


3.繼承的優(yōu)缺點

優(yōu)點:

1.功能復(fù)用

直接將已有的屬性和行為繼承過來,實現(xiàn)了功能的復(fù)用,節(jié)省了大量的工作

2.便于拓展新功能

在已有的功能的基礎(chǔ)上,更容易建立,擴充新功能

3.結(jié)構(gòu)清晰,簡化認(rèn)識

同屬性一個繼承體系的相關(guān)類,他們直接結(jié)構(gòu)層次清晰,簡化了人們對代碼結(jié)構(gòu)的認(rèn)識

4.易于維護

不同類之間的繼承關(guān)系,讓這些事物之間保持一定程度的一致性,大大降低了維護成本

缺點:

1.打破了封裝性

父類向子類暴露了實現(xiàn)細節(jié),打破了父類對象的封裝性

2.高耦合性

類與類之間緊密的結(jié)合在一起,相互依賴性高

程序設(shè)計的追求

低耦合,高內(nèi)聚

-耦合:兩個(或更多)模塊相互依賴于對方

-內(nèi)聚:模塊內(nèi)部結(jié)構(gòu)緊密,獨立性強

4.繼承關(guān)系中類成員的使用

1.繼承關(guān)系中父類成員變量的使用

this和super的區(qū)別

this

-本質(zhì):對象

-用法:從本類開始找

super

-本質(zhì):父類內(nèi)存空間的標(biāo)識

-用法:從父類開始找

例子

需求:子父類中定義了同名的成員變量,如果使用?

分析:

A:子類中定義成員變量 int price ,默認(rèn)值為10

B:父類中定義成員變量int price ,默認(rèn)值為20

C:子類成員方法中定義局部變量int price ,默認(rèn)值為 5

D:在子類成員方法中分別輸出三個price的值

//定義父類 Fruit 水果類

public class Fruit {

??? //成員變量

? ? //價格

? ? int price =20;

}

//定義一個子類 Apple 蘋果類

public class Appleextends? Fruit{

??? //成員變量

? ? //價格

? ? private int price =10;

??? //成員方法

? ? public void showPrice(){

??? ??? int price =5;

??? ??? System.out.println(price);//局部變量price 5

? ? ? ? System.out.println(this.price);//子類成員變量price 10

? ? ? ? System.out.println(super.price);//父類成員變量price 20

? ? }

}

//測試類

public class Test {

??? public static void main(String[] args) {

? ? ? ? //測試?yán)^承關(guān)系中,子父類之間成員變量的使用

? ? ? ? //1.創(chuàng)建一個子類對象 蘋果類對象

? ? ? ? Apple apple =new Apple();

? ? ? ? //2.調(diào)用對象方法

? ? ? ? apple.showPrice();

? ? ? ? /*

? ? ? ? ? ? ? ? java中使用變量的規(guī)則,遵循就近原則

? ? ? ? ? ? ? ? 局部位置有就使用,沒有就去本類的成員位置找

? ? ? ? ? ? ? ? 有就使用,沒有就去父類的成員位置找

? ? ? ? ? ? ? ? 有就使用,沒有就報錯*/

? ? }

}

運行結(jié)果:


2.繼承關(guān)系中子父類成員方法的使用

例子

需求:子父類中定義了同名的成員方法,如何使用

定義武功類Martial:

練習(xí)內(nèi)功:internalStrength()

練習(xí)招式:stroke()

定義九陰真經(jīng)類NineYin:

練習(xí)內(nèi)功:internalStrength()

練習(xí)招式:stroke()

九陰真經(jīng)的修煉,不僅要練習(xí)基本內(nèi)功還需要以柔克剛,需要擴展父類中的方法

簡單的招式已經(jīng)不足以未用,必須有九陰白骨爪這樣的大招才可以使用,需要重新實現(xiàn)父類中的方法

//定義一個父類 Martial 武功類

public class Martial {

??? //成員方法

? ? //練習(xí)內(nèi)功

? ? public void internalStrength(){

??? ??? System.out.println("練習(xí)內(nèi)功");

??? }

??? //練習(xí)招式

? ? public void stroke(){

??? ??? System.out.println("練習(xí)招式");

??? }

}

//定義一個子類 NineYin 九陰真經(jīng)類 繼承父類 Martial 武功類

public class NineYinextends Martial{

? ? //成員方法

? ? //練習(xí)內(nèi)功

? ? public void internalStrength(){

? ? ? ? //調(diào)用父類中的成員方法

? ? ? ? super.internalStrength();

? ? ? ? System.out.println("練習(xí)以柔克剛");

? ? }

? ? public void stroke(){

? ? ? ? System.out.println("練習(xí)九陰白骨爪");

? ? }

}

//測試類

public class Test {

??? public static void main(String[] args) {

??? ??? //需求:調(diào)用NineYin中的方法

? ? ? ? NineYin nineYin =new NineYin();

??? ??? nineYin.internalStrength();

??? ??? nineYin.stroke();

??? }

}

運行結(jié)果:


結(jié)論:

1.查找方法的原則:

就近原則

2.查找方法的順序

本類->父類->更高的父類....Object

3.訪問父類方法的方式

super.父類方法名()

4.定義重名方法的前提

父類功能不能萬確滿足實現(xiàn)需求,擴展父類功能

父類功能已過時,重新實現(xiàn)父類方法

3.繼承關(guān)系中子父類構(gòu)造方法的使用

需求:創(chuàng)建對象時,構(gòu)造方法時如何被調(diào)用的?

分析:

A:定義父類Person,在默認(rèn)無參構(gòu)造中輸出語句

B:定義子類Worker,繼承Person,在默認(rèn)無參構(gòu)造中輸出語句

C:定義測試類,創(chuàng)建子類Worker對象

結(jié)論

·創(chuàng)建子類對象時,優(yōu)先調(diào)用父類構(gòu)造方法

·子類構(gòu)造方法的第一行,隱含語句super(),用于調(diào)用父類的默認(rèn)無參構(gòu)造

需求:父類不存在默認(rèn)的無參構(gòu)造方法怎么辦?

分析:子類創(chuàng)建對象時,必須先初始化該對象父類內(nèi)容,若父類中不存在默認(rèn)無參構(gòu)造,必須手動調(diào)用父類其他構(gòu)造

//定義一個父類Person

public class Person {

? ? //構(gòu)造方法

? ? //無參構(gòu)造

? ? public Person(String name){

? ? ? ? //System.out.println("Person類的無參構(gòu)造");

? ? ? ? System.out.println("Person類的帶參構(gòu)造");

? ? }

}

//定義一個子類Worker

public class Workerextends Person {

? ? //構(gòu)造方法

? ? //無參構(gòu)造

? ? public Worker(){

? ? ? ? //super();//默認(rèn)調(diào)用父類的無參構(gòu)造

? ? ? ? //System.out.println("Worker類的無參構(gòu)造");

? ? ? ? super("張三");

? ? ? ? System.out.println("Worker類的帶參構(gòu)造");

? ? }

}

/*

? ? 子類的構(gòu)造方法中都會有一個默認(rèn)的surper();用來訪問父類的無參構(gòu)造方法

? ? 如果父類沒有無參構(gòu)造,可以通過surper(參數(shù))用來訪問父類的帶參構(gòu)造*/

public class Test {

? ? public static void main(String[] args) {

? ? ? ? //創(chuàng)建一個子類Worker類的對象

? ? ? ? Worker worker =new Worker();

? ? }

}

運行結(jié)果:


5.方法的重寫(Override)

·定義:

子類中出現(xiàn)和父類定義相同的方法的現(xiàn)象

·解釋:

方法重寫也叫方法復(fù)寫,覆蓋

方法名,參數(shù)列表,返回值類型都要相同

·注意事項:

父類私有方法無法重寫

子類方法訪問權(quán)限不能小于父類方法

子類不能比父類方法拋出更大的異常

使用場景:

擴展父類功能

父類功能過時,重新實現(xiàn)父類功能

四大權(quán)限修飾符修飾范圍,從小到大分別是:

private,默認(rèn)(什么都不寫就是默認(rèn)),protected,public

1.Java中的訪問權(quán)限修飾符

prvate 本類

默認(rèn)? ? 本類、本包下的類中

protected 本類、本包下的類中、不同包下的子類中

public 本類、本包下的類中、不同包下的子類中、其他類中

總結(jié)

private:強調(diào)的是給自己使用

默認(rèn):強調(diào)的是給通報下的類使用

protected:強調(diào)的是給子類使用

public:強調(diào)的是給大家使用

2.方法重寫和方法重載的區(qū)別

重載

方法名:相同

參數(shù)列表:不同(個數(shù)或?qū)?yīng)位置類型)

返回值:無關(guān)

定義位置:同一個類

重寫

方法名:相同

參數(shù)列表:相同

返回值類型:相同

修飾符:訪問權(quán)限不小于被重寫的方法

定義位置:子父類中

6.java中繼承的特點

·單繼承

Java只支持類的單繼承,但是支持多層(重)繼承

Java支持接口的多繼承,語法為:

接口A extends 接口B,接口C,接口D....

·私有成員不能繼承

只能繼承父類中的非私有成員(成員變量,成員方法)

·構(gòu)造方法不能被繼承

構(gòu)造方法用于初始化本類對象

創(chuàng)建子類對象時,需要調(diào)用父類構(gòu)造方法初始化

該對象父類內(nèi)容,若父類構(gòu)造可以被繼承

該操作會造成調(diào)用混亂

·繼承體系了“is a”的關(guān)系

子類符合“is a”父類的情況,才能使用繼承,其他情況不建議使用

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容