從屌絲到架構(gòu)師的飛越(面向?qū)ο笃?繼承

一、介紹

繼承是面向?qū)ο笞铒@著的一個(gè)特性。繼承是從已有的類(lèi)中派生出新的類(lèi),新的類(lèi)能吸收已有類(lèi)的數(shù)據(jù)屬性和行為,并能擴(kuò)展新的能力。Java繼承是使用已存在的類(lèi)的定義作為基礎(chǔ)建立新類(lèi)的技術(shù),新類(lèi)的定義可以增加新的數(shù)據(jù)或新的功能,也可以用父類(lèi)的功能,但不能選擇性地繼承父類(lèi)。這種技術(shù)使得復(fù)用以前的代碼非常容易,能夠大大縮短開(kāi)發(fā)周期,降低開(kāi)發(fā)費(fèi)用。

在面向?qū)ο蟪绦蛟O(shè)計(jì)中運(yùn)用繼承原則,就是在每個(gè)由一般類(lèi)和特殊類(lèi)形成的一般——特殊結(jié)構(gòu)中,把一般類(lèi)的對(duì)象實(shí)例和所有特殊類(lèi)的對(duì)象實(shí)例都共同具有的屬性和操作一次性地在一般類(lèi)中進(jìn)行顯式的定義,在特殊類(lèi)中不再重復(fù)地定義一般類(lèi)中已經(jīng)定義的東西,但是在語(yǔ)義上,特殊類(lèi)卻自動(dòng)地、隱含地?fù)碛兴囊话泐?lèi)(以及所有更上層的一般類(lèi))中定義的屬性和操作。特殊類(lèi)的對(duì)象擁有其一般類(lèi)的全部或部分屬性與方法,稱(chēng)作特殊類(lèi)對(duì)一般類(lèi)的繼承。

比如可以先定義一個(gè)類(lèi)叫車(chē),車(chē)有以下屬性:車(chē)體大小,顏色,方向盤(pán),輪胎,而又由車(chē)這個(gè)類(lèi)派生出轎車(chē)和卡車(chē)兩個(gè)類(lèi),為轎車(chē)添加一個(gè)小后備箱,而為卡車(chē)添加一個(gè)大貨箱。

二、知識(shí)點(diǎn)介紹

1、繼承概念

2、繼承的定義及使用格式

3、繼承注意事項(xiàng)

4、方法重寫(xiě)

三、上課對(duì)應(yīng)視頻的說(shuō)明文檔

1、繼承概念

1.1、繼承概述

繼承是面向?qū)ο蟮暮诵奶匦裕敲嫦驅(qū)ο蟮膶W(xué)習(xí)重點(diǎn)。同時(shí)繼承是代碼復(fù)用的重要方式,可以表示類(lèi)與類(lèi)之間的關(guān)系,是所有面向?qū)ο笳Z(yǔ)言不可缺少的組成部分。

1.2、繼承概念

當(dāng)一個(gè)類(lèi)的屬性與行為均與現(xiàn)有類(lèi)相似,屬于現(xiàn)有類(lèi)的一種時(shí),這一個(gè)類(lèi)可以定義為現(xiàn)有類(lèi)的子類(lèi)。

或者換成相反的角度來(lái)看,如果多個(gè)類(lèi)具有相同的屬性和行為,我們可以抽取出共性的內(nèi)容定義父類(lèi),這時(shí)再創(chuàng)建相似的類(lèi)時(shí)只要繼承父類(lèi)即可。

子類(lèi)擁有父類(lèi)的所有屬性與方法,無(wú)需重新定義。并且可以直接使用非私有的父類(lèi)成員。

從類(lèi)與類(lèi)之間的設(shè)計(jì)關(guān)系來(lái)看,子類(lèi)必須屬于父類(lèi)的一種時(shí),才會(huì)繼承。

我們?cè)谕瓿梢粋€(gè)龐大項(xiàng)目體系的時(shí)候,都是將共性的內(nèi)容抽取出,后續(xù)構(gòu)建過(guò)程是從各種父類(lèi)“向外”擴(kuò)散的。

下例展示了一個(gè)繼承關(guān)系

圖1-1 動(dòng)物繼承關(guān)系圖

動(dòng)物類(lèi)可以有姓名、年齡的成員變量,可以有吃飯、睡覺(jué)的方法。

所有貓科與犬科均有動(dòng)物的成員變量與成員方法,且貓科與犬科均屬于動(dòng)物,所以貓科與全科均可以繼承動(dòng)物類(lèi)。

貓科可以在動(dòng)物的基礎(chǔ)上再添加抓老鼠的方法

犬科可以在動(dòng)物的基礎(chǔ)上再添加看門(mén)的方法

犬科與貓科仍可以繼續(xù)出現(xiàn)子類(lèi),如波斯貓、巴厘貓、沙皮狗、斑點(diǎn)狗等,而其子類(lèi)仍可以再出現(xiàn)該品種的特性。

2、繼承定義及使用格式

2.1、繼承定義

class 子類(lèi) extends 父類(lèi){

//父類(lèi)的非私有方法與屬性均繼承過(guò)來(lái)

}

如:

父類(lèi)的定義:

class Person{

private String name;

public void eat(){

System.out.println(“吃飯”);

}

get/set方法

}

子類(lèi)繼承父類(lèi)的定義:

class Chinese extends Person{}

2.2、繼承使用

繼承關(guān)系的產(chǎn)生通常是為了定義出功能更為具體、更為強(qiáng)大的子類(lèi)。所以,定義子類(lèi)后,一般創(chuàng)建子類(lèi)對(duì)象使用。子類(lèi)可以直接使用父類(lèi)非私有的成員變量與成員方法

(注:如果成員變量沒(méi)有使用private修飾,則子類(lèi)也可直接訪問(wèn)。)

子類(lèi)的使用:

class Test{

public static void main(String[] args) {

Chinese? c = new Chinese();

c.setName(“張大力”);

String name = c.getName();

System.out.println(name);//打印結(jié)果為張大力

c.eat();? //打印結(jié)果吃飯

}

3、繼承注意事項(xiàng)

Java只支持單繼承,不支持多繼承。即只能有一個(gè)父類(lèi)。

父類(lèi)可以繼續(xù)有父類(lèi)。

所有類(lèi)均有父類(lèi),只有Object類(lèi)沒(méi)有父類(lèi)。

在所有使用父類(lèi)類(lèi)型的地方均可以傳入其子類(lèi)對(duì)象。

/*

* Animal的類(lèi)

* 屬性

*? ? ? ? name

*? ? ? ? age

* 行為

*? ? ? ? 吃

*? ? ? ? 睡

*/

public class Animal {

//成員變量

private String name;

private int age;

// //吃

// public abstract void eat(){

//? ? System.out.println(“吃”);

//? ? }

//睡

public void sleep(){

System.out.println("睡");

}

//-----------get/set-------------------

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

}

/*

*定義一個(gè)貓類(lèi)

* 屬性

*? name?

*? age

*? kind

* 行為

*? 吃

*? 睡

*? 抓老鼠

*/

public class Cat extends Animal{

private String kind;

// @Override

// public void eat(){

//? System.out.println("貓吃魚(yú)");

// }

//貓?zhí)赜械墓δ? 抓老鼠

public void catchMouse(){

System.out.println("抓耗子");

}

public String getKind() {

return kind;

}

public void setKind(String kind) {

this.kind = kind;

}

}

/*

*定義一個(gè)狗類(lèi)

* 屬性

*? name?

*? age

*? kind

* 行為

*? 吃

*? 睡

*? 看門(mén)

*/

public class Dog extends Animal{

private String kind;

// @Override

// public void eat(){

//? System.out.println("狗吃肉");

// }

//狗特有功能? 看門(mén)

public void lookDoor(){

System.out.println("看門(mén)");

}

public String getKind() {

return kind;

}

public void setKind(String kind) {

this.kind = kind;

}

}

/*

* 自定義類(lèi)型 家

*

*? 地址

*

* 行為

*? 在家吃飯

*/

public class Home {

private String address;

//動(dòng)物在家吃飯

//在所有使用父類(lèi)類(lèi)型的地方均可以傳入其子類(lèi)對(duì)象。

public void eatAtHome(Animal a){

//調(diào)用Animal的eat方法

//a.eat();?

}

//狗在在家吃飯

// public void eatAtHome(Dog dog){

//? System.out.println("狗在家吃了");

//? //調(diào)用狗的eat方法

//? dog.eat();

// }

//貓?jiān)诩页燥?/p>

// public void eatAtHome(Cat cat){

//? System.out.println("貓?jiān)诩俪粤?);

//? //調(diào)用貓的eat方法

//? cat.eat();

// }

public String getAddress() {

return address;

}

public void setAddress(String address) {

this.address = address;

}

}

/**

* 測(cè)試家類(lèi)

*/

public class Test {

public static void main(String[] args) {

//? 創(chuàng)建Home對(duì)象

Home home = new? Home();

//? Animal a = new Animal();?

//? home.eatAtHome(a);?

//在所有使用父類(lèi)類(lèi)型的地方均可以傳入其子類(lèi)對(duì)象。

Dog d = new Dog();

home.eatAtHome(d);

Cat c = new Cat();

home.eatAtHome(c);?

}

}

4、方法重寫(xiě)

4.1、方法重寫(xiě)概念

當(dāng)子類(lèi)繼承父類(lèi)后,擁有了父類(lèi)的成員并可以直接調(diào)用父類(lèi)非私有方法。如果子類(lèi)認(rèn)為父類(lèi)提供的方法不夠強(qiáng)大,子類(lèi)可以按照子類(lèi)自身的邏輯重新定義繼承過(guò)來(lái)的父類(lèi)方法,這個(gè)重新定義一個(gè)方法的過(guò)程叫做方法重寫(xiě)。

(注:在學(xué)習(xí)完多態(tài)和抽象類(lèi)后我們會(huì)對(duì)方法重寫(xiě)有更深的理解)

4.2、方法重寫(xiě)格式

子類(lèi)中定義與父類(lèi)一樣的方法便將父類(lèi)的方法重寫(xiě)了。此時(shí),當(dāng)創(chuàng)建子類(lèi)對(duì)象,調(diào)用方法時(shí),會(huì)調(diào)用子類(lèi)重寫(xiě)后的方法。如:

子類(lèi)中定義與父類(lèi)一樣的方法聲明即是方法重寫(xiě)。

如:

父類(lèi)定義:

public class Person{

private String name;

public void eat(){

System.out.println(“吃飯”);

}

get/set

}

子類(lèi)定義:

public class Chinese extends Person{

@override //@override是用于強(qiáng)制規(guī)定當(dāng)前定義的方法一定為重寫(xiě)的方法

public void eat() {

System.out.println(“按照中國(guó)的習(xí)慣,使用筷子吃”);

}

}

子類(lèi)的使用:

public class Test{

public static void main(String[] args) {

Chinese? c = new Chinese();

c.setName(“張大力”);? //父類(lèi)繼承方法直接調(diào)用

String name = c.getName(); //父類(lèi)繼承方法直接調(diào)用

System.out.println(name); //打印結(jié)果為張大力

c.eat();? //方法重寫(xiě)后調(diào)用的為重寫(xiě)后的方法

//打印結(jié)果:按照中國(guó)的習(xí)慣,使用筷子吃

}

}

/**

* 自定義類(lèi)型? 人類(lèi)

*

*? ? 姓名? 年齡

*/

public class Person {

String address;

private String name;

private int age;

public void eat(){

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

}

public void sleep(){

System.out.println("睡");

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

}

/*

* 定義類(lèi)型? 學(xué)生類(lèi)

*

* 姓名? 年齡

*

* 繼承

*? 概念1? 當(dāng)定義一個(gè)類(lèi)時(shí),發(fā)現(xiàn)現(xiàn)有類(lèi)與要定義的類(lèi)類(lèi)似,并且要定義的類(lèi)屬于現(xiàn)有類(lèi)的一種時(shí),

*? 就可以將這個(gè)類(lèi)定義為現(xiàn)有類(lèi)的子類(lèi)

*?

*? 子類(lèi)擁有父類(lèi)的所有屬性與方法,無(wú)需重新定義。并且可以直接使用非私有的父類(lèi)成員。

*?

*? 父類(lèi)私用的成員變量? 可以使用get/set方法 訪問(wèn)

*? 父類(lèi)私有的方法? 沒(méi)有辦法直接方法? 雖然繼承了 但是相當(dāng)于沒(méi)有

*? ?

*? 子類(lèi)可以有自己特有的屬性和方法

*?

*? 方法重寫(xiě)

*? ? 子類(lèi)繼承父類(lèi)后,可以直接使用父類(lèi)的非私有成員,但是如果覺(jué)得父類(lèi)的成員方法不夠強(qiáng)大,子類(lèi)可以按照自身的邏輯

*? ? 將繼承過(guò)來(lái)的父類(lèi)方法,進(jìn)行重寫(xiě)(方法重寫(xiě),方法復(fù)寫(xiě),方法覆蓋)

*?

*? 可以使用@Override來(lái)驗(yàn)證你的方法是不是重寫(xiě)方法。

*/

public class Student extends Person{

private String number;

public void method(){

System.out.println(address);

System.out.println(getName());

}

//重寫(xiě)父類(lèi)eat方法

@Override

public void eat(){

System.out.println("學(xué)生吃學(xué)生套餐");

}

public String getNumber() {

return number;

}

public void setNumber(String number) {

this.number = number;

}

}

/*

* 測(cè)試?yán)^承后的Studnet

*/

public class Test {

public static void main(String[] args) {

//創(chuàng)建Studnet對(duì)象

Student s = new Student();

s.setName("柳柳");

s.setNumber("0900112");

s.eat();

//? s.sleep();

String name = s.getName();

System.out.println(name);

System.out.println(s.getNumber());

System.out.println("-----------------");

//子類(lèi)調(diào)用自己特有的方法

s.method();?

}

}

4.3、Java中方法重寫(xiě)規(guī)則

子類(lèi)重寫(xiě)方法時(shí),在聲明前加@Override可檢測(cè)該方法是否為重寫(xiě)的方法

訪問(wèn)權(quán)限相同或子類(lèi)方法訪問(wèn)權(quán)限更大(訪問(wèn)權(quán)限順序public>默認(rèn))

class Fu{

void show(){}

public void method(){}

}

class Zi extends Fu{

public void show(){}? //編譯運(yùn)行沒(méi)問(wèn)題

void method(){}? ? ? //編譯錯(cuò)誤

}

方法名稱(chēng)必須相同

參數(shù)列表必須相同

返回值為基本類(lèi)型時(shí)必須相同

返回值為引用類(lèi)型時(shí)相同或子類(lèi)小(了解)

/*

* 方法重寫(xiě)的注意事項(xiàng)

*? 子類(lèi)重寫(xiě)方法時(shí),在聲明前加@Override可檢測(cè)該方法是否為重寫(xiě)的方法

*? 訪問(wèn)權(quán)限相同或子類(lèi)方法訪問(wèn)權(quán)限更大(訪問(wèn)權(quán)限順序public>默認(rèn))

*? 方法名稱(chēng)必須相同

*? 參數(shù)列表必須相同

*? 返回值為基本類(lèi)型時(shí)必須相同

*? 返回值為引用類(lèi)型時(shí)相同或子類(lèi)小(了解)

*/

public class Fu {

public void method(){

System.out.println(" 父類(lèi)方法");

}

public int sum(){

return 0;

}

public Person get(){

return null;

}

}

public class Zi extends Fu{

//訪問(wèn)權(quán)限相同或子類(lèi)方法訪問(wèn)權(quán)限更大(訪問(wèn)權(quán)限順序public>默認(rèn))

@Override

public void method(){

System.out.println("子類(lèi)方法");

}

//返回值為基本類(lèi)型時(shí)必須相同

@Override

public int sum(){

return 100;

}

//返回值為引用類(lèi)型時(shí)相同或子類(lèi)小(了解)

@Override

public Student get(){

return null;

}

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容