目錄
為什么需要繼承
繼承的概念
繼承的語(yǔ)法
注意事項(xiàng)
?父類成員訪問(wèn)
子類中訪問(wèn)父類的成員變量
子類和父類不存在同名成員變量
子類和父類成員變量同名
訪問(wèn)原則
子類中訪問(wèn)父類的成員方法
成員方法名字不同
總結(jié):
成員方法名字相同
總結(jié):
super關(guān)鍵字
注意事項(xiàng)
子類構(gòu)造方法
注意事項(xiàng)
super和this
相同點(diǎn)
不同點(diǎn)
再談初始化
繼承關(guān)系上的執(zhí)行順序
?編輯?結(jié)論:
?protected 關(guān)鍵字
同一個(gè)包中的子類
不同包中的子類
?不同包中的類
注意:
限定修飾符使用的時(shí)機(jī)
繼承方式
注意事項(xiàng)?
final 關(guān)鍵字
修飾變量或字段
修飾類
修飾方法
繼承與組合
總結(jié)
為什么需要繼承
Java中使用類對(duì)現(xiàn)實(shí)世界中實(shí)體來(lái)進(jìn)行描述,類經(jīng)過(guò)實(shí)例化之后的產(chǎn)物對(duì)象,則可以用來(lái)表示現(xiàn)實(shí)中的實(shí)體,但是現(xiàn)實(shí)世界錯(cuò)綜復(fù)雜,事物之間可能會(huì)存在一些關(guān)聯(lián),那在設(shè)計(jì)程序是就需要考慮。
比如:狗和貓,它們都是一個(gè)動(dòng)物
如果我們需要用java語(yǔ)言來(lái)描述它們,我們會(huì)寫(xiě)出以下代碼
比如狗類
public class Dog{
string name;
int age;
float weight;
public void eat(){
System.out.println(name + "正在吃飯");
}
public void sleep(){
System.out.println(name + "正在睡覺(jué)");
}
void Bark(){
System.out.println(name + "汪汪汪~(yú)~~");
}
}
?貓類
public class Cat{
string name;
int age;
float weight;
public void eat(){
System.out.println(name + "正在吃飯");
}
public void sleep()
{
System.out.println(name + "正在睡覺(jué)");
}
void mew(){
System.out.println(name + "喵喵喵~~~");
}
}
通過(guò)觀察上述代碼會(huì)發(fā)現(xiàn),貓和狗的類中存在大量重復(fù),如下所示
那能否將這些共性抽取呢?面向?qū)ο笏枷胫刑岢隽死^承的概念,專門用來(lái)進(jìn)行共性抽取,實(shí)現(xiàn)代碼復(fù)用。
繼承的概念
繼承(inheritance)機(jī)制:是面向?qū)ο蟪绦蛟O(shè)計(jì)使代碼可以復(fù)用的最重要的手段,它允許程序員在保持原有類特 性的基礎(chǔ)上進(jìn)行擴(kuò)展,增加新功能,這樣產(chǎn)生新的類,稱派生類。繼承呈現(xiàn)了面向?qū)ο蟪绦蛟O(shè)計(jì)的層次結(jié)構(gòu), 體現(xiàn)了由簡(jiǎn)單到復(fù)雜的認(rèn)知過(guò)程。繼承主要解決的問(wèn)題是:共性的抽取,實(shí)現(xiàn)代碼復(fù)用。
例如:狗和貓都是動(dòng)物,那么我們就可以將共性的內(nèi)容進(jìn)行抽取,然后采用繼承的思想來(lái)達(dá)到共用
上述圖示中,Dog和Cat都繼承了Animal類,其中:Animal類稱為父類/基類或超類,Dog和Cat可以稱為Animal的子類/派生類,繼承之后,子類可以復(fù)用父類中成員,子類在實(shí)現(xiàn)時(shí)只需關(guān)心自己新增加的成員即可。
從繼承概念中可以看出繼承最大的作用就是:實(shí)現(xiàn)代碼復(fù)用,還有就是來(lái)實(shí)現(xiàn)多態(tài)(后序講)
繼承的語(yǔ)法
在Java中如果要表示類之間的繼承關(guān)系,需要借助extends關(guān)鍵字,具體如下:
修飾符 class 子類 extends 父類 {
// ...
}
然后我們對(duì)上述代碼進(jìn)行改造以下,帶大家感受一下繼承
首先把狗類與貓類所擁有的共同元素書(shū)寫(xiě)成一個(gè)Animal類
public class Animal{
String name;
int age;
public void eat() {
System.out.println(name + "正在吃飯");
}
public void sleep() {
System.out.println(name + "正在睡覺(jué)");
}
}
接下來(lái)我們用繼承來(lái)實(shí)現(xiàn)一下我們的Dog類
public class Dog extends Animal{
void bark(){
System.out.println(name + "汪汪汪~(yú)~~");
}
}
Cat類同理
public class Cat extends Animal{
void mew(){
System.out.println(name + "喵喵喵~~~");
}
}
實(shí)例化對(duì)象如下
public class TestExtend {
public static void main(String[] args) {
Dog dog = new Dog();
// dog類中并沒(méi)有定義任何成員變量,name和age屬性肯定是從父類Animal中繼承下來(lái)的
System.out.println(dog.name);
System.out.println(dog.age);
// dog訪問(wèn)的eat()和sleep()方法也是從Animal中繼承下來(lái)的
dog.eat();
dog.sleep();
dog.bark();
}
}
注意事項(xiàng)
1. 子類會(huì)將父類中的成員變量或者成員方法繼承到子類中了
2. 子類繼承父類之后,必須要新添加自己特有的成員,體現(xiàn)出與基類的不同,否則就沒(méi)有必要繼承了
?父類成員訪問(wèn)
在繼承體系中,子類將父類中的方法和字段繼承下來(lái)了,那在子類中能否直接訪問(wèn)父類中繼承下來(lái)的成員呢?
子類中訪問(wèn)父類的成員變量
子類和父類不存在同名成員變量
public class Base {
int a;
int b;
}
public class Derived extends Base{
int c;
public void method(){
a = 10; // 訪問(wèn)從父類中繼承下來(lái)的a
b = 20; // 訪問(wèn)從父類中繼承下來(lái)的b
c = 30; // 訪問(wèn)子類自己的c
}
}
子類和父類成員變量同名
public class Base {
int a;
int b;
int c;
}
/
public class Derived extends Base{
int a; // 與父類中成員a同名,且類型相同
char b; // 與父類中成員b同名,但類型不同
public void method(){
a = 100; // 訪問(wèn)子類自己新增的a
b = 101; // 訪問(wèn)子類自己新增的b
c = 102; // 子類沒(méi)有c,訪問(wèn)的肯定是從父類繼承下來(lái)的c
// d = 103; // 編譯失敗,因?yàn)楦割惡妥宇惗紱](méi)有定義成員變量b
}
}
訪問(wèn)原則
在子類方法中 或者 通過(guò)子類對(duì)象訪問(wèn)成員時(shí):
如果訪問(wèn)的成員變量子類中有,優(yōu)先訪問(wèn)自己的成員變量。
如果訪問(wèn)的成員變量子類中無(wú),則訪問(wèn)父類繼承下來(lái)的,如果父類也沒(méi)有定義,則編譯報(bào)錯(cuò)。
如果訪問(wèn)的成員變量與父類中成員變量同名,則優(yōu)先訪問(wèn)自己的。
成員變量訪問(wèn)遵循就近原則,自己有優(yōu)先自己的,如果沒(méi)有則向父類中找
子類中訪問(wèn)父類的成員方法
成員方法名字不同
public class Base {
public void methodA(){
System.out.println("Base中的methodA()");
}
}
public class Derived extends Base{
public void methodB(){
System.out.println("Derived中的methodB()方法");
}
public void methodC(){
methodB(); // 訪問(wèn)子類自己的methodB()
methodA(); // 訪問(wèn)父類繼承的methodA()
// methodD(); // 編譯失敗,在整個(gè)繼承體系中沒(méi)有發(fā)現(xiàn)方法methodD()
}
}
總結(jié):
成員方法沒(méi)有同名時(shí),在子類方法中或者通過(guò)子類對(duì)象訪問(wèn)方法時(shí),則優(yōu)先訪問(wèn)自己的,自己沒(méi)有時(shí),再到父類中找,如果父類中也沒(méi)有則報(bào)錯(cuò)。
成員方法名字相同
public class Base {
public void methodA(){
System.out.println("Base中的methodA()");
}
public void methodB(){
System.out.println("Base中的methodB()");
}
}
public class Derived extends Base{
public void methodA(int a) {
System.out.println("Derived中的method(int)方法");
}
public void methodB(){
System.out.println("Derived中的methodB()方法");
}
public void methodC(){
methodA(); // 沒(méi)有傳參,訪問(wèn)父類中的methodA()
methodA(20); // 傳遞int參數(shù),訪問(wèn)子類中的methodA(int)
methodB(); // 直接訪問(wèn),則永遠(yuǎn)訪問(wèn)到的都是子類中的methodB(),基類的無(wú)法訪問(wèn)到
}
}
總結(jié):
1、通過(guò)子類對(duì)象訪問(wèn)父類與子類中不同名方法時(shí),優(yōu)先在子類中找,找到則訪問(wèn),否則在父類中找,找到則訪問(wèn),否則編譯報(bào)錯(cuò)。
2、通過(guò)派生類對(duì)象訪問(wèn)父類與子類同名方法時(shí),如果父類和子類同名方法的參數(shù)列表不同(重載),根據(jù)調(diào)用方法適傳遞的參數(shù)選擇合適的方法訪問(wèn),如果沒(méi)有則報(bào)錯(cuò);
那么問(wèn)題來(lái)了,如果子類中存在與父類中相同的成員時(shí),那如何在子類中訪問(wèn)父類相同名稱的成員呢?請(qǐng)看下文
super關(guān)鍵字
由于設(shè)計(jì)不好,或者因場(chǎng)景需要,子類和父類中可能會(huì)存在相同名稱的成員,如果要在子類方法中訪問(wèn)父類同名成員時(shí),該如何操作?
直接訪問(wèn)是無(wú)法做到的,Java提供了super關(guān)鍵字,該關(guān)鍵字主要作用:在子類方法中訪問(wèn)父
類的成員
例如我這兒有一個(gè)Base類
public class Base {
int a;
int b;
public void methodA(){
System.out.println("Base中的methodA()");
}
public void methodB(){
System.out.println("Base中的methodB()");
}
}
我們將它作為父類,我們現(xiàn)在有一個(gè)子類Derived類
public class Derived extends Base{
int a; // 與父類中成員變量同名且類型相同
char b; // 與父類中成員變量同名但類型不同
// 與父類中methodA()構(gòu)成重載
public void methodA(int a) {
System.out.println("Derived中的method()方法");
}
// 與基類中methodB()構(gòu)成重寫(xiě)(即原型一致,重寫(xiě)后序詳細(xì)介紹)
public void methodB(){
System.out.println("Derived中的methodB()方法");
}
public void methodC(){
// 對(duì)于同名的成員變量,直接訪問(wèn)時(shí),訪問(wèn)的都是子類的
a = 100; // 等價(jià)于: this.a = 100;
b = 101; // 等價(jià)于: this.b = 101;
// 注意:this是當(dāng)前對(duì)象的引用
// 訪問(wèn)父類的成員變量時(shí),需要借助super關(guān)鍵字
// super是獲取到子類對(duì)象中從基類繼承下來(lái)的部分
super.a = 200;
super.b = 201;
// 父類和子類中構(gòu)成重載的方法,直接可以通過(guò)參數(shù)列表區(qū)分清訪問(wèn)父類還是子類方法
methodA(); // 沒(méi)有傳參,訪問(wèn)父類中的methodA()
methodA(20); // 傳遞int參數(shù),訪問(wèn)子類中的methodA(int)
// 如果在子類中要訪問(wèn)重寫(xiě)的基類方法,則需要借助super關(guān)鍵字
methodB(); // 直接訪問(wèn),則永遠(yuǎn)訪問(wèn)到的都是子類中的methodA(),基類的無(wú)法訪問(wèn)到
super.methodB(); // 訪問(wèn)基類的methodB()
}
}
public class Base {
public Base() {
System.out.println("Base()");
}
}
在子類方法中,如果想要明確訪問(wèn)父類中成員時(shí),借助super關(guān)鍵字即可
注意事項(xiàng)
1. 只能在非靜態(tài)方法中使用
2. 在子類方法中,訪問(wèn)父類的成員變量和方法
子類構(gòu)造方法
父子父子,先有父再有子,即:子類對(duì)象構(gòu)造時(shí),需要先調(diào)用基類構(gòu)造方法,然后執(zhí)行子類的構(gòu)造方法
public class Base {
public Base(){
System.out.println("Base()");
}
}
public class Derived extends Base{
public Derived(){
// super(); // 注意子類構(gòu)造方法中默認(rèn)會(huì)調(diào)用基類的無(wú)參構(gòu)造方法:super(),
// 用戶沒(méi)有寫(xiě)時(shí),編譯器會(huì)自動(dòng)添加,而且super()必須是子類構(gòu)造方法中第一條語(yǔ)句,
// 并且只能出現(xiàn)一次
System.out.println("Derived()");
}
}
public class Test {
public static void main(String[] args) {
Derived d = new Derived();
}
}
結(jié)果為
?在子類構(gòu)造方法中,并沒(méi)有寫(xiě)任何關(guān)于基類構(gòu)造的代碼,但是在構(gòu)造子類對(duì)象時(shí),先執(zhí)行基類的構(gòu)造方法,然后執(zhí)行子類的構(gòu)造方法
因?yàn)椋鹤宇悓?duì)象中成員是有兩部分組成的,基類繼承下來(lái)的以及子類新增加的部分 。父子父子肯定是先有父再有子,所以在構(gòu)造子類對(duì)象時(shí)候 ,先要調(diào)用基類的構(gòu)造方法,將從基類繼承下來(lái)的成員構(gòu)造完整,然后再調(diào)用子類自己的構(gòu)造方法,將子類自己新增加的成員初始化完整 。
注意事項(xiàng)
1. 若父類顯式定義無(wú)參或者默認(rèn)的構(gòu)造方法,在子類構(gòu)造方法第一行默認(rèn)有隱含的super()調(diào)用,即調(diào)用基類構(gòu)造方法
2. 如果父類構(gòu)造方法是帶有參數(shù)的,此時(shí)需要用戶為子類顯式定義構(gòu)造方法,并在子類構(gòu)造方法中選擇合適的父類構(gòu)造方法調(diào)用,否則編譯失敗。
3. 在子類構(gòu)造方法中,super(...)調(diào)用父類構(gòu)造時(shí),必須是子類構(gòu)造函數(shù)中第一條語(yǔ)句。
4. super(...)只能在子類構(gòu)造方法中出現(xiàn)一次,并且不能和this同時(shí)出現(xiàn)
super和this
super和this都可以在成員方法中用來(lái)訪問(wèn):成員變量和調(diào)用其他的成員函數(shù),都可以作為構(gòu)造方法的第一條語(yǔ)句,
那他們之間有什么區(qū)別呢?
相同點(diǎn)
1. 都是Java中的關(guān)鍵字
2. 只能在類的非靜態(tài)方法中使用,用來(lái)訪問(wèn)非靜態(tài)成員方法和字段
3. 在構(gòu)造方法中調(diào)用時(shí),必須是構(gòu)造方法中的第一條語(yǔ)句,并且不能同時(shí)存在
不同點(diǎn)
1. this是當(dāng)前對(duì)象的引用,當(dāng)前對(duì)象即調(diào)用實(shí)例方法的對(duì)象,super相當(dāng)于是子類對(duì)象中從父類繼承下來(lái)部分成員的引用
2. 在非靜態(tài)成員方法中,this用來(lái)訪問(wèn)本類的方法和屬性,super用來(lái)訪問(wèn)父類繼承下來(lái)的方法和屬性
3. 在構(gòu)造方法中:this(...)用于調(diào)用本類構(gòu)造方法,super(...)用于調(diào)用父類構(gòu)造方法,兩種調(diào)用不能同時(shí)在構(gòu)造方法中出現(xiàn)
4. 構(gòu)造方法中一定會(huì)存在super(...)的調(diào)用,用戶沒(méi)有寫(xiě)編譯器也會(huì)增加,但是this(...)用戶不寫(xiě)則沒(méi)有
再談初始化
我們還記得之前講過(guò)的代碼塊嗎?我們簡(jiǎn)單回顧一下幾個(gè)重要的代碼塊:實(shí)例代碼塊和靜態(tài)代碼塊。在沒(méi)有繼承關(guān)系時(shí)的執(zhí)行順序。
class Person {
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("構(gòu)造方法執(zhí)行");
}
{
System.out.println("實(shí)例代碼塊執(zhí)行");
}
static {
System.out.println("靜態(tài)代碼塊執(zhí)行");
}
}
public class TestDemo {
public static void main(String[] args) {
Person person1 = new Person("bit",10);
System.out.println("============================");
Person person2 = new Person("gaobo",20);
}
}
運(yùn)行結(jié)果如下
我們發(fā)現(xiàn)執(zhí)行順序
1. 靜態(tài)代碼塊先執(zhí)行,并且只執(zhí)行一次,在類加載階段執(zhí)行
2. 當(dāng)有對(duì)象創(chuàng)建時(shí),才會(huì)執(zhí)行實(shí)例代碼塊,實(shí)例代碼塊執(zhí)行完成后,最后構(gòu)造方法執(zhí)行
繼承關(guān)系上的執(zhí)行順序
為了看清楚著中間的執(zhí)行順序,我們有以下代碼
class Person {
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("Person:構(gòu)造方法執(zhí)行");
}
{
System.out.println("Person:實(shí)例代碼塊執(zhí)行");
}
static {
System.out.println("Person:靜態(tài)代碼塊執(zhí)行");
}
}
class Student extends Person{
public Student(String name,int age) {
super(name,age);
System.out.println("Student:構(gòu)造方法執(zhí)行");
}
{
System.out.println("Student:實(shí)例代碼塊執(zhí)行");
}
static {
System.out.println("Student:靜態(tài)代碼塊執(zhí)行");
}
}
public class TestDemo {
public static void main(String[] args) {
Student student1 = new Student("張三",19);
System.out.println("===========================");
Student student2 = new Student("gaobo",20);
}
public static void main1(String[] args) {
Person person1 = new Person("bit",10);
System.out.println("============================");
Person person2 = new Person("gaobo",20);
}
}
運(yùn)行結(jié)果
?結(jié)論:
1、父類靜態(tài)代碼塊優(yōu)先于子類靜態(tài)代碼塊執(zhí)行,且是最早執(zhí)行
2、父類實(shí)例代碼塊和父類構(gòu)造方法緊接著執(zhí)行
3、子類的實(shí)例代碼塊和子類構(gòu)造方法緊接著再執(zhí)行
4、第二次實(shí)例化子類對(duì)象時(shí),父類和子類的靜態(tài)代碼塊都將不會(huì)再執(zhí)行
?
?protected 關(guān)鍵字
在類和對(duì)象章節(jié)中,為了實(shí)現(xiàn)封裝特性,Java中引入了訪問(wèn)限定符,主要限定:類或者類中成員能否在類外或者其他包中被訪問(wèn)。
那父類中不同訪問(wèn)權(quán)限的成員,在子類中的可見(jiàn)性又是什么樣子的呢?
比如我們現(xiàn)在有一個(gè)父類叫B類,我將它放在extend01包中
public class B {
private int a;
protected int b;
public int c;
int d;
}
同一個(gè)包中的子類
D類我也放在extend01包中
public class D extends B{
public void method(){
// super.a = 10; // 編譯報(bào)錯(cuò),父類private成員在相同包子類中不可見(jiàn)
super.b = 20; // 父類中protected成員在相同包子類中可以直接訪問(wèn)
super.c = 30; // 父類中public成員在相同包子類中可以直接訪問(wèn)
super.d = 40; // 父類中默認(rèn)訪問(wèn)權(quán)限修飾的成員在相同包子類中可以直接訪問(wèn)
}
}
不同包中的子類
我將C類放在extend02包中
public class C extends B {
public void method(){
// super.a = 10; // 編譯報(bào)錯(cuò),父類中private成員在不同包子類中不可見(jiàn)
super.b = 20; // 父類中protected修飾的成員在不同包子類中可以直接訪問(wèn)
super.c = 30; // 父類中public修飾的成員在不同包子類中可以直接訪問(wèn)
//super.d = 40; // 父類中默認(rèn)訪問(wèn)權(quán)限修飾的成員在不同包子類中不能直接訪問(wèn)
}
}
?不同包中的類
在剛剛那個(gè)包創(chuàng)建C類的基礎(chǔ)上,在再該包創(chuàng)建一個(gè)TestC類,并加入我們的主函數(shù)
public class TestC {
public static void main(String[] args) {
C c = new C();
c.method();
// System.out.println(c.a); // 編譯報(bào)錯(cuò),父類中private成員在不同包其他類中不可見(jiàn)
// System.out.println(c.b); // 父類中protected成員在不同包其他類中不能直接訪問(wèn)
System.out.println(c.c); // 父類中public成員在不同包其他類中可以直接訪問(wèn)
// System.out.println(c.d); // 父類中默認(rèn)訪問(wèn)權(quán)限修飾的成員在不同包其他類中不能直接訪問(wèn)
}
}
注意:
父類中private成員變量雖然在子類中不能直接訪問(wèn),但是也繼承到子類中了
限定修飾符使用的時(shí)機(jī)
這么多限定修飾符,那我們應(yīng)該在什么時(shí)候用什么修飾符呢?
相信很多人都有這樣的疑問(wèn)
我們希望類要盡量做到 "封裝", 即隱藏內(nèi)部實(shí)現(xiàn)細(xì)節(jié), 只暴露出 必要 的信息給類的調(diào)用者.
因此我們?cè)谑褂玫臅r(shí)候應(yīng)該盡可能的使用 比較嚴(yán)格 的訪問(wèn)權(quán)限. 例如如果一個(gè)方法能用 private, 就盡量不要用 public.
另外, 還有一種 簡(jiǎn)單粗暴 的做法: 將所有的字段設(shè)為 private, 將所有的方法設(shè)為 public. 不過(guò)這種方式屬于是對(duì)訪問(wèn)權(quán)限的濫用, 還是更希望同學(xué)們能寫(xiě)代碼的時(shí)候認(rèn)真思考, 該類提供的字段方法到底給 "誰(shuí)" 使用(是類內(nèi)部自己用, 還是類的調(diào)用者使用, 還是子類使用)
?
繼承方式
在現(xiàn)實(shí)生活中,事物之間的關(guān)系是非常復(fù)雜,靈活多樣,比如:
但在Java中只支持以下幾種繼承方式:
注意事項(xiàng)?
Java中不支持多繼承。
時(shí)刻牢記, 我們寫(xiě)的類是現(xiàn)實(shí)事物的抽象. 而我們真正在公司中所遇到的項(xiàng)目往往業(yè)務(wù)比較復(fù)雜, 可能會(huì)涉及到一系列復(fù)雜的概念, 都需要我們使用代碼來(lái)表示, 所以我們真實(shí)項(xiàng)目中所寫(xiě)的類也會(huì)有很多. 類之間的關(guān)系也會(huì)更加復(fù)雜.
但是即使如此, 我們并不希望類之間的繼承層次太復(fù)雜. 一般我們不希望出現(xiàn)超過(guò)三層的繼承關(guān)系. 如果繼承層次太多, 就需要考慮對(duì)代碼進(jìn)行重構(gòu)了.
有些同學(xué)就想我能不能不讓別人繼承我的呢??
當(dāng)然是可以的,如果想從語(yǔ)法上進(jìn)行限制繼承, 就可以使用 final 關(guān)鍵字
final 關(guān)鍵字
final關(guān)鍵可以用來(lái)修飾變量、成員方法以及類。
修飾變量或字段
表示常量(即不能修改)
final int a = 10;
a = 20; // 編譯出錯(cuò)
修飾類
表示此類不能被繼承
final public class Animal {
...
}
public class Bird extends Animal {
...
}
// 編譯出錯(cuò)
Error:(3, 27) java: 無(wú)法從最終com.bit.Animal進(jìn)行繼
我們平時(shí)是用的 String 字符串類, 就是用 final 修飾的, 不能被繼承
修飾方法
表示該方法不能被重寫(xiě),博主會(huì)在后續(xù)進(jìn)行介紹
繼承與組合
和繼承類似, 組合也是一種表達(dá)類之間關(guān)系的方式, 也是能夠達(dá)到代碼重用的效果。組合并沒(méi)有涉及到特殊的語(yǔ)法(諸如 extends 這樣的關(guān)鍵字), 僅僅是將一個(gè)類的實(shí)例作為另外一個(gè)類的字段。
繼承表示對(duì)象之間是is-a的關(guān)系,比如:狗是動(dòng)物,貓是動(dòng)物
組合表示對(duì)象之間是has-a的關(guān)系,比如:汽車
汽車和其輪胎、發(fā)動(dòng)機(jī)、方向盤、車載系統(tǒng)等的關(guān)系就應(yīng)該是組合,因?yàn)槠囀怯羞@些部件組成的?
// 輪胎類
class Tire{
// ...
}
// 發(fā)動(dòng)機(jī)類
class Engine{
// ...
}
// 車載系統(tǒng)類
class VehicleSystem{
// ...
}
class Car{
private Tire tire; // 可以復(fù)用輪胎中的屬性和方法
private Engine engine; // 可以復(fù)用發(fā)動(dòng)機(jī)中的屬性和方法
private VehicleSystem vs; // 可以復(fù)用車載系統(tǒng)中的屬性和方法
// ...
}
// 奔馳是汽車
class Benz extend Car{
// 將汽車中包含的:輪胎、發(fā)送機(jī)、車載系統(tǒng)全部繼承下來(lái)
}
組合和繼承都可以實(shí)現(xiàn)代碼復(fù)用,應(yīng)該使用繼承還是組合,需要根據(jù)應(yīng)用場(chǎng)景來(lái)選擇,一般建議:能用組合盡量用組合
如果有同學(xué)想詳細(xì)了解繼承與組合可以點(diǎn)下方鏈接,進(jìn)行了解,我這里就不做過(guò)多贅述了
深入理解Java中的組合和繼承-HollisChuang's Bloghttps://www.hollischuang.com/archives/1319
總結(jié)
關(guān)于《面向?qū)ο蟪绦蛉筇匦灾^承》就講解到這兒,歡迎各位留言交流以及批評(píng)指正,如果文章對(duì)您有幫助或者覺(jué)得作者寫(xiě)的還不錯(cuò)可以點(diǎn)一下關(guān)注,點(diǎn)贊,收藏支持一下。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-621171.html
?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-621171.html
到了這里,關(guān)于【javaSE】 面向?qū)ο蟪绦蛉筇匦灾^承的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!