9.0 Java面向?qū)ο笕筇匦?/h3>
-
封裝眯停、繼承产雹、多態(tài)。從一定角度來看驮宴,封裝和繼承幾乎都是為多態(tài)而準(zhǔn)備的
-
多態(tài)概念:指允許不同類的對(duì)象對(duì)同一消息做出響應(yīng)球化。即同一消息可以根據(jù)發(fā)送對(duì)象的不同而采用多種不同的行為方式秽晚。(發(fā)送消息就是函數(shù)調(diào)用)
-
動(dòng)態(tài)綁定(dynamic binding),是指在執(zhí)行期間判斷所引用對(duì)象的實(shí)際類型筒愚,根據(jù)其實(shí)際的類型調(diào)用其相應(yīng)的方法赴蝇。
- 關(guān)于多態(tài)的例子不勝枚舉。比方說按下 F1 鍵這個(gè)動(dòng)作巢掺,如果當(dāng)前在 Flash 界面下彈出的就是 AS 3 的幫助文檔句伶;如果當(dāng)前在 Word 下彈出的就是 Word 幫助劲蜻;在 Windows 下彈出的就是 Windows 幫助和支持。同一個(gè)事件發(fā)生在不同的對(duì)象上會(huì)產(chǎn)生不同的結(jié)果
9.1 Java面向?qū)ο螅ǘ鄳B(tài)的概述及其代碼體現(xiàn))
-
多態(tài)(polymorphic)概述
- 事物存在多種形態(tài)
-
多態(tài)前提(三個(gè)必要條件)
- 1.要有繼承關(guān)系
- 2.要有方法重寫
- 3.要有父類引用指向子類對(duì)象
Animal an = new Cat(); //父類引用指向子類對(duì)象
an.eat(); //行為結(jié)果卻是子類的行為
9.2 多態(tài)中的成員訪問特點(diǎn)
- 1.成員變量
- 編譯看左邊考余,運(yùn)行看左邊先嬉。
- 2.成員方法
- 編譯看左邊(父類),運(yùn)行看右邊(子類)楚堤。(動(dòng)態(tài)綁定)
- 3.靜態(tài)方法
- 編譯看左邊疫蔓,運(yùn)行看左邊。
- 靜態(tài)和類相關(guān)身冬,算不上重寫衅胀,所以訪問還是看左邊。
- 只有非靜態(tài)的成員方法吏恭,編譯看左邊拗小,運(yùn)行看右邊重罪。
9.3 多態(tài)中的向上轉(zhuǎn)型 和 向下轉(zhuǎn)型
class Person {
String name = "普通人";
public void xxoo () {
System.out.println("我是普通人...");
}
}
class SuperMan extends Person {
String name = "超人";
public void xxoo () {
System.out.println("我是超人...");
}
public void fly() {
System.out.println("超人會(huì)飛...");
}
}
Person p = new SuperMan(); //向上轉(zhuǎn)型樱哼。父類引用指向子類對(duì)象
SuperMan sm = (SuperMan)p; //向下轉(zhuǎn)型。
Person p = new SuperMan(); //父類引用指向子類對(duì)象
System.out.println(p.name); //成員屬性剿配,輸出父類的屬性值
p.xxoo(); //成員方法搅幅,運(yùn)行結(jié)果 是子類的行為
p.fly(); //編譯錯(cuò)誤,子類的方法呼胚,父類指針內(nèi)部 找不到子類方法茄唐,只有強(qiáng)制轉(zhuǎn)型之后,才可以使用蝇更。
System.out.println("---------------");
SuperMan sm = (SuperMan)p;
System.out.println(sm.name);
sm.xxoo();
sm.fly();
9.4多態(tài)的優(yōu)缺點(diǎn)
- 多態(tài)的好處:
- 1.提高了代碼的可維護(hù)性(繼承保證)
- 2.提高了代碼的擴(kuò)展性(多態(tài)保證)
- 3.可以當(dāng)作形參沪编,接收任意子類對(duì)象
- 多態(tài)的弊端
- 不能使用子類特有的屬性和行為(需要強(qiáng)轉(zhuǎn))
// 方法 參數(shù)是 動(dòng)物類
public void method(Animal aniaml) {
// 關(guān)鍵字 instanceof 判斷前面的引用是否是后邊的數(shù)據(jù)類型
if (aniaml instanceof Cat) {
Cat cat = (Cat)aniaml ;
}
else if (aniaml instanceof Dog) {
Dog dog = (Dog)aniaml ;
}
else return ;
}
9.5多態(tài)代碼題
- 題目一:多態(tài)的理解
class Fu { // 父類
int num = 10;
public void show() {
System.out.println("fu show");
}
}
class Zi extends Fu { // 子類
int num = 20 ;
public void show() {
System.out.println("zi show");
}
}
// 運(yùn)行代碼
Fu fu = new Zi();
System.out.println(fu.num); // 結(jié)果10 :成員變量,編譯看左邊年扩,運(yùn)行看左邊
fu.show(); // 結(jié)果 "zi show" 成員方法蚁廓,編譯看左邊,運(yùn)行看右邊
9.6 抽象類
- A:抽象類概述
- 抽象就是看不懂的
- B:抽象類的特點(diǎn)
-
1.抽象類和抽象方法必須用 abstract
關(guān)鍵字修飾
abstract class ClassName {}
-
public abstract void xxoo() ;
//注意沒有{ }
2.抽象類不一定有抽象方法厨幻,有抽象方法的類一定是抽象類或者接口
3.抽象類不能直接實(shí)例化相嵌,必須由其具體子類實(shí)例化,所謂 抽象類多態(tài)
4.抽象類的子類:要么是抽象類况脆,要么重寫抽象類中的所有抽象方法
abstract class Animal { //抽象類
int num = 10;
static final int num2 = 200 ;
public void sleep() {} //普通方法
public abstract void eat() ; //抽象方法
}
class Cat extends Animal { // 子類實(shí)現(xiàn)抽象類
public void eat() {
System.out.println("貓吃魚");
}
}
// Cat 繼承并實(shí)現(xiàn)了 抽象類Animal
Animal cat = new Cat();
cat.eat();
// 匿名內(nèi)部類 的方式實(shí)例化抽象類
// 只要一個(gè)類是抽象的或是一個(gè)接口饭宾,那么其子類中的方法都可以使用匿名內(nèi)部類來實(shí)現(xiàn)
// 這種方式常見于 多線程的實(shí)現(xiàn)上,因?yàn)橐獙?shí)現(xiàn)多線程必須繼承Thread類或是繼承Runnable接口
Animal dog = new Animal() {
public void eat() {
System.out.println("狗啃骨頭");
}
};
dog.eat();
- 抽象類的成員特點(diǎn):
- 1.成員變量:既可以是變量格了,也可以是常量看铆。
abstract
不能修飾變量/常量
- 2.抽象類有構(gòu)造方法(必須有啊,不然子類怎么
super()
)
- 3.成員方法: 既可以是抽象的盛末,也可以是非抽象的性湿。
9.7 抽象類面試題
-
A.面試題一
-
一個(gè)抽象類如沒有抽象方法纬傲,可不可以定義為抽象類?如果可以肤频,有什么意義叹括?
- 可以
- 這么做的目的只有一個(gè):就是不讓其他類創(chuàng)建本類對(duì)象,交給子類完成宵荒。
-
面試題二
-
abstract
不能和哪些關(guān)鍵字共存汁雷?
- 不能和:
final
、static
报咳、private
共存
9.8 接口
-
A.接口概述
- 從狹義角度講就是指的java中的
interface
- 從廣義角度講對(duì)外提供規(guī)則的都是接口
-
B.接口特點(diǎn)
- 1.接口用關(guān)鍵字
interface
聲明表示:
- 2.類實(shí)現(xiàn)接口用
implements
表示
- 3.接口不能直接實(shí)例化侠讯,需要實(shí)現(xiàn)接口的類,或者多態(tài)的方式
- 4.接口的子類可以是抽象類(但是意義不大)暑刃,也可以是具體類厢漩,實(shí)現(xiàn)接口中所有的抽象方法。
9.9 接口的成員特點(diǎn)
- A:成員變量岩臣,只能是常量溜嗜,并且是靜態(tài)的公共的。
- 默認(rèn)修飾符是:
public
架谎、static
炸宵、final
- 構(gòu)造方法:接口沒有構(gòu)造方法,實(shí)現(xiàn)接口谷扣,不是繼承土全!
- 成員方法:只能是抽象方法。默認(rèn)修飾符:
public
会涎、abstract
裹匙,建議自己手動(dòng)給出。
interface InreName { //接口定義
int num = 10; //成員變量末秃,只能是常量概页,并且是 public、static蛔溃、final
public abstract void print(); //接口中的方法都是抽象的
}
class Demo implements InreName { //實(shí)現(xiàn)接口
public void print() {
System.out.println("實(shí)現(xiàn)接口的全部方法");
}
}
9.10 類與類绰沥,類與接口,接口與接口的關(guān)系
- 類與類:
- 繼承關(guān)系贺待,只能單繼承徽曲,可以多層繼承
- 類與接口:
- 實(shí)現(xiàn)關(guān)系,可以單實(shí)現(xiàn)麸塞,也可以多實(shí)現(xiàn)秃臣;可以繼承一個(gè)類的同時(shí),實(shí)現(xiàn)多個(gè)接口。
- 接口與接口:
- 繼承關(guān)系奥此,可以單繼承弧哎,也可以多繼承。
class ClassB extends ClassA implements InterA,InterB {
// 類可以繼承一個(gè)類的同時(shí)稚虎,實(shí)現(xiàn)多個(gè)接口
}
interface InterC extends InterA, InterB {
// 接口可以多繼承其他接口撤嫩,切只能是接口
}
9.11 抽象類與接口的區(qū)別
多態(tài)(polymorphic)概述
- 事物存在多種形態(tài)
多態(tài)前提(三個(gè)必要條件)
- 1.要有繼承關(guān)系
- 2.要有方法重寫
- 3.要有父類引用指向子類對(duì)象
Animal an = new Cat(); //父類引用指向子類對(duì)象
an.eat(); //行為結(jié)果卻是子類的行為
- 編譯看左邊考余,運(yùn)行看左邊先嬉。
- 編譯看左邊(父類),運(yùn)行看右邊(子類)楚堤。(動(dòng)態(tài)綁定)
- 編譯看左邊疫蔓,運(yùn)行看左邊。
- 靜態(tài)和類相關(guān)身冬,算不上重寫衅胀,所以訪問還是看左邊。
- 只有非靜態(tài)的成員方法吏恭,編譯看左邊拗小,運(yùn)行看右邊重罪。
class Person {
String name = "普通人";
public void xxoo () {
System.out.println("我是普通人...");
}
}
class SuperMan extends Person {
String name = "超人";
public void xxoo () {
System.out.println("我是超人...");
}
public void fly() {
System.out.println("超人會(huì)飛...");
}
}
Person p = new SuperMan(); //向上轉(zhuǎn)型樱哼。父類引用指向子類對(duì)象
SuperMan sm = (SuperMan)p; //向下轉(zhuǎn)型。
Person p = new SuperMan(); //父類引用指向子類對(duì)象
System.out.println(p.name); //成員屬性剿配,輸出父類的屬性值
p.xxoo(); //成員方法搅幅,運(yùn)行結(jié)果 是子類的行為
p.fly(); //編譯錯(cuò)誤,子類的方法呼胚,父類指針內(nèi)部 找不到子類方法茄唐,只有強(qiáng)制轉(zhuǎn)型之后,才可以使用蝇更。
System.out.println("---------------");
SuperMan sm = (SuperMan)p;
System.out.println(sm.name);
sm.xxoo();
sm.fly();
- 1.提高了代碼的可維護(hù)性(繼承保證)
- 2.提高了代碼的擴(kuò)展性(多態(tài)保證)
- 3.可以當(dāng)作形參沪编,接收任意子類對(duì)象
- 不能使用子類特有的屬性和行為(需要強(qiáng)轉(zhuǎn))
// 方法 參數(shù)是 動(dòng)物類
public void method(Animal aniaml) {
// 關(guān)鍵字 instanceof 判斷前面的引用是否是后邊的數(shù)據(jù)類型
if (aniaml instanceof Cat) {
Cat cat = (Cat)aniaml ;
}
else if (aniaml instanceof Dog) {
Dog dog = (Dog)aniaml ;
}
else return ;
}
class Fu { // 父類
int num = 10;
public void show() {
System.out.println("fu show");
}
}
class Zi extends Fu { // 子類
int num = 20 ;
public void show() {
System.out.println("zi show");
}
}
// 運(yùn)行代碼
Fu fu = new Zi();
System.out.println(fu.num); // 結(jié)果10 :成員變量,編譯看左邊年扩,運(yùn)行看左邊
fu.show(); // 結(jié)果 "zi show" 成員方法蚁廓,編譯看左邊,運(yùn)行看右邊
- 抽象就是看不懂的
-
1.抽象類和抽象方法必須用
abstract
關(guān)鍵字修飾abstract class ClassName {}
-
public abstract void xxoo() ;
//注意沒有{ }
2.抽象類不一定有抽象方法厨幻,有抽象方法的類一定是抽象類或者接口
3.抽象類不能直接實(shí)例化相嵌,必須由其具體子類實(shí)例化,所謂 抽象類多態(tài)
4.抽象類的子類:要么是抽象類况脆,要么重寫抽象類中的所有抽象方法
abstract class Animal { //抽象類
int num = 10;
static final int num2 = 200 ;
public void sleep() {} //普通方法
public abstract void eat() ; //抽象方法
}
class Cat extends Animal { // 子類實(shí)現(xiàn)抽象類
public void eat() {
System.out.println("貓吃魚");
}
}
// Cat 繼承并實(shí)現(xiàn)了 抽象類Animal
Animal cat = new Cat();
cat.eat();
// 匿名內(nèi)部類 的方式實(shí)例化抽象類
// 只要一個(gè)類是抽象的或是一個(gè)接口饭宾,那么其子類中的方法都可以使用匿名內(nèi)部類來實(shí)現(xiàn)
// 這種方式常見于 多線程的實(shí)現(xiàn)上,因?yàn)橐獙?shí)現(xiàn)多線程必須繼承Thread類或是繼承Runnable接口
Animal dog = new Animal() {
public void eat() {
System.out.println("狗啃骨頭");
}
};
dog.eat();
- 1.成員變量:既可以是變量格了,也可以是常量看铆。
abstract
不能修飾變量/常量 - 2.抽象類有構(gòu)造方法(必須有啊,不然子類怎么
super()
) - 3.成員方法: 既可以是抽象的盛末,也可以是非抽象的性湿。
A.面試題一
- 一個(gè)抽象類如沒有抽象方法纬傲,可不可以定義為抽象類?如果可以肤频,有什么意義叹括?
- 可以
- 這么做的目的只有一個(gè):就是不讓其他類創(chuàng)建本類對(duì)象,交給子類完成宵荒。
面試題二
-
abstract
不能和哪些關(guān)鍵字共存汁雷? - 不能和:
final
、static
报咳、private
共存
A.接口概述
- 從狹義角度講就是指的java中的
interface
- 從廣義角度講對(duì)外提供規(guī)則的都是接口
B.接口特點(diǎn)
- 1.接口用關(guān)鍵字
interface
聲明表示: - 2.類實(shí)現(xiàn)接口用
implements
表示 - 3.接口不能直接實(shí)例化侠讯,需要實(shí)現(xiàn)接口的類,或者多態(tài)的方式
- 4.接口的子類可以是抽象類(但是意義不大)暑刃,也可以是具體類厢漩,實(shí)現(xiàn)接口中所有的抽象方法。
- 默認(rèn)修飾符是:
public
架谎、static
炸宵、final
public
会涎、abstract
裹匙,建議自己手動(dòng)給出。interface InreName { //接口定義
int num = 10; //成員變量末秃,只能是常量概页,并且是 public、static蛔溃、final
public abstract void print(); //接口中的方法都是抽象的
}
class Demo implements InreName { //實(shí)現(xiàn)接口
public void print() {
System.out.println("實(shí)現(xiàn)接口的全部方法");
}
}
- 繼承關(guān)系贺待,只能單繼承徽曲,可以多層繼承
- 實(shí)現(xiàn)關(guān)系,可以單實(shí)現(xiàn)麸塞,也可以多實(shí)現(xiàn)秃臣;可以繼承一個(gè)類的同時(shí),實(shí)現(xiàn)多個(gè)接口。
- 繼承關(guān)系奥此,可以單繼承弧哎,也可以多繼承。
class ClassB extends ClassA implements InterA,InterB {
// 類可以繼承一個(gè)類的同時(shí)稚虎,實(shí)現(xiàn)多個(gè)接口
}
interface InterC extends InterA, InterB {
// 接口可以多繼承其他接口撤嫩,切只能是接口
}
成員變量 | 構(gòu)造方法 | 成員方法 | |
---|---|---|---|
抽象類 | 可以是變量,也可以是常量 | 有 | 可以抽象蠢终,也可以不抽象 |
接口 | 只可以常量 | 無 | 只可以抽象 |
設(shè)計(jì)理念區(qū)別:
- 抽象類 被繼承體現(xiàn)的是 is a 的關(guān)系序攘,抽象類中定義的是該繼承體系的共性功能。
- 接口 被實(shí)現(xiàn)體現(xiàn)的是 like a 的關(guān)系寻拂,接口中定義的是改繼承體系的擴(kuò)展功能程奠。
END。
我是小侯爺祭钉。
在魔都艱苦奮斗瞄沙,白天是上班族,晚上是知識(shí)服務(wù)工作者慌核。
如果讀完覺得有收獲的話距境,記得關(guān)注和點(diǎn)贊哦。
非要打賞的話遂铡,我也是不會(huì)拒絕的肮疗。