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)清晰鳖粟,簡化認識
同屬性一個繼承體系的相關(guān)類社裆,他們直接結(jié)構(gòu)層次清晰,簡化了人們對代碼結(jié)構(gòu)的認識
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)存空間的標識
-用法:從父類開始找
例子
需求:子父類中定義了同名的成員變量,如果使用吕嘀?
分析:
A:子類中定義成員變量 int price ,默認值為10
B:父類中定義成員變量int price ,默認值為20
C:子類成員方法中定義局部變量int price ,默認值為 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) {
? ? ? ? //測試繼承關(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,在默認無參構(gòu)造中輸出語句
B:定義子類Worker,繼承Person,在默認無參構(gòu)造中輸出語句
C:定義測試類碟摆,創(chuàng)建子類Worker對象
結(jié)論:
·創(chuàng)建子類對象時晃财,優(yōu)先調(diào)用父類構(gòu)造方法
·子類構(gòu)造方法的第一行,隱含語句super()典蜕,用于調(diào)用父類的默認無參構(gòu)造
需求:父類不存在默認的無參構(gòu)造方法怎么辦?
分析:子類創(chuàng)建對象時断盛,必須先初始化該對象父類內(nèi)容,若父類中不存在默認無參構(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();//默認調(diào)用父類的無參構(gòu)造
? ? ? ? //System.out.println("Worker類的無參構(gòu)造");
? ? ? ? super("張三");
? ? ? ? System.out.println("Worker類的帶參構(gòu)造");
? ? }
}
/*
? ? 子類的構(gòu)造方法中都會有一個默認的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,默認(什么都不寫就是默認),protected,public
1.Java中的訪問權(quán)限修飾符
prvate 本類
默認? ? 本類馏鹤、本包下的類中
protected 本類征椒、本包下的類中、不同包下的子類中
public 本類湃累、本包下的類中勃救、不同包下的子類中碍讨、其他類中
總結(jié)
private:強調(diào)的是給自己使用
默認:強調(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”父類的情況益兄,才能使用繼承锻梳,其他情況不建議使用