??博客主頁(yè):愛(ài)敲代碼的小楊.
?專欄:《Java SE語(yǔ)法》
??感謝大家點(diǎn)贊????收藏?評(píng)論???,您的三連就是我持續(xù)更新的動(dòng)力??
面向?qū)ο笕筇匦裕悍庋b、繼承和多態(tài)。
1. 封裝
1.1 封裝的概念
在面向?qū)ο蟪淌皆O(shè)計(jì)方法中,封裝(英語(yǔ):Encapsulation)是指一種將抽象性函式接口的實(shí)現(xiàn)細(xì)節(jié)部份包裝、隱藏起來(lái)的方法。
封裝可以被認(rèn)為是一個(gè)保護(hù)屏障,防止該類的代碼和數(shù)據(jù)被外部類定義的代碼隨機(jī)訪問(wèn)。
要訪問(wèn)該類的代碼和數(shù)據(jù),必須通過(guò)嚴(yán)格的接口控制。
封裝最主要的功能在于我們能修改自己的實(shí)現(xiàn)代碼,而不用修改那些調(diào)用我們代碼的程序片段。
適當(dāng)?shù)姆庋b可以讓程式碼更容易理解與維護(hù),也加強(qiáng)了程式碼的安全性。
1.2 為什么封裝
封裝的目的是保護(hù)數(shù)據(jù)的安全和完整性,同時(shí)隱藏?cái)?shù)據(jù)的實(shí)現(xiàn)細(xì)節(jié),提高代碼的可維護(hù)性和可擴(kuò)展性,具體有以下幾個(gè)方面的好處:
- 良好的封裝能夠減少耦合。
- 類內(nèi)部的結(jié)構(gòu)可以自由修改。
- 可以對(duì)成員變量進(jìn)行更精確的控制。
- 隱藏信息,實(shí)現(xiàn)細(xì)節(jié)。
1.3 封裝的實(shí)現(xiàn)步驟
-
修改屬性的可見(jiàn)性來(lái)限制屬性的訪問(wèn)(用
private
來(lái)修飾),如:public class Test { private String name; private int age; }
這段代碼中,將
name
和age
屬性設(shè)置為私有的,只有在本類中被訪問(wèn),其他類訪問(wèn)不了,就實(shí)現(xiàn)對(duì)信息的隱藏。 -
對(duì)每個(gè)值屬性提供對(duì)外的公共方法訪問(wèn),也就是創(chuàng)建一對(duì)賦取值方法,用于對(duì)私有屬性的訪問(wèn),例如:
public class Test { private String name; private int age; 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; } }
采用
this
關(guān)鍵字是為了解決實(shí)例變量和局部變量之間發(fā)生的同名的沖突。
2. 繼承
2.1 繼承的概念
繼承是 java
面向?qū)ο缶幊碳夹g(shù)的一塊基石,因?yàn)樗试S創(chuàng)建分等級(jí)層次的類。
繼承就是子類繼承父類的特征和行為,使得子類對(duì)象(實(shí)例)具有父類的實(shí)例域和方法,或子類從父類繼承方法,使得子類具有父類相同的行為。
生活中的繼承
兔子和羊?qū)儆谑巢輨?dòng)物,獅子和老虎屬于食肉動(dòng)物。
食草動(dòng)物和食肉動(dòng)物又是屬于動(dòng)物。
所有的繼承需要符合的關(guān)系:is-a,父類更通用,子類更具體。
雖然食草動(dòng)物和食肉動(dòng)物都是屬于動(dòng)物,但是兩者的屬性和行為上有差別,所以子類會(huì)具有父類的一般特性也會(huì)具有自身的特性。
2.2 繼承的格式
在 Java
中通過(guò)關(guān)鍵字 extends
來(lái)聲明一個(gè)類是從另一個(gè)類繼承而來(lái)的,一般格式如下:
class 父類 {
}
class 子類 extends 父類 {
}
2.3 為什么繼承
接下來(lái)我們通過(guò)實(shí)例的說(shuō)明這個(gè)需求。
開(kāi)發(fā)動(dòng)物類,其中動(dòng)物分別為狗和貓,要求如下:
- 狗:屬性(姓名,顏色),方法(吃,叫)
- 貓:屬性(姓名,顏色),方法(吃,叫)
class Dog{
private String name;
private String color;
public void eat() {
System.out.println(this.name + "正在吃...");
}
public void cry() {
System.out.println(this.name + "正在叫...");
}
}
class Cat {
private String name;
private String color;
public void eat() {
System.out.println(this.name + "正在吃...");
}
public void cry() {
System.out.println(this.name + "正在叫...");
}
}
從這兩段代碼可以看出來(lái),代碼存在重復(fù)了,導(dǎo)致后果就是代碼量大且臃腫,而且維護(hù)性不高(維護(hù)性主要是后期需要修改的時(shí)候,就需要修改很多的代碼,容易出錯(cuò)),所以要從根本上解決這兩段代碼的問(wèn)題,就需要繼承,將兩段代碼中相同的部分提取出來(lái)組成 一個(gè)父類:
class Animal {
private String name;
private String color;
public Animal(String name, String color) {
this.name = name;
this.color = color;
}
public void eat() {
System.out.println(this.name + "正在吃...");
}
public void cry() {
System.out.println(this.name + "正在叫...");
}
}
這個(gè)Animal類就可以作為一個(gè)父類,然后狗類和貓類繼承這個(gè)類之后,就具有父類當(dāng)中的屬性和方法,子類就不會(huì)存在重復(fù)的代碼,維護(hù)性也提高,代碼也更加簡(jiǎn)潔,提高代碼的復(fù)用性(復(fù)用性主要是可以多次使用,不用再多次寫同樣的代碼) 繼承之后的代碼:
- 狗類
class Dog extends Animal{
public Dog(String name , String color) {
super(name, color);
}
}
- 貓類
class Cat extends Animal {
public Cat(String name , String color) {
super(name, color);
}
}
2.4 繼承類型
Java
中不支持多繼承,但支持多重繼承。
2.5 繼承特性
- 子類擁有父類非
private
的屬性、方法。 - 子類可以擁有自己的屬性和方法,即子類可以對(duì)父類進(jìn)行擴(kuò)展。
- 子類可以用自己的方式實(shí)現(xiàn)父類的方法。
- Java 的繼承是單繼承,但是可以多重繼承,單繼承就是一個(gè)子類只能繼承一個(gè)父類,多重繼承就是,例如 A 類繼承 B 類,B 類繼承 C 類,所以按照關(guān)系就是 C 類是 B 類的父類,B 類是 A 類的父類,這是 Java 繼承區(qū)別于 C++ 繼承的一個(gè)特性。
- 提高了類之間的耦合性(繼承的缺點(diǎn),耦合度高就會(huì)造成代碼之間的聯(lián)系越緊密,代碼獨(dú)立性越差)。
2.6 super 與 this 關(guān)鍵字
super
關(guān)鍵字:我們可以通過(guò)super
關(guān)鍵字來(lái)實(shí)現(xiàn)對(duì)父類成員的訪問(wèn),用來(lái)引用當(dāng)前對(duì)象的父類
this
關(guān)鍵字:指向自己的引用。
class Animal {
void eat() {
System.out.println("animal : eat");
}
}
class Dog extends Animal {
void eat() {
System.out.println("dog : eat");
}
void eatTest() {
this.eat(); // this 調(diào)用自己的方法
super.eat(); // super 調(diào)用父類方法
}
}
public class Test {
public static void main(String[] args) {
Animal a = new Animal();
a.eat();
Dog d = new Dog();
d.eatTest();
}
}
// 運(yùn)行結(jié)果
//animal : eat
//dog : eat
//animal : eat
2.7 final 關(guān)鍵字
final
關(guān)鍵字聲明類可以把類定義為不能繼承的,即最終類;或者用于修飾方法,該方法不能被子類重寫;
- 聲明類
final class 類名 {
// 類體
}
- 聲明方法
訪問(wèn)限定符 final 返回值類型 方法名(){
// 方法體
}
注意:實(shí)例變量也可以被定義為final
,被定義為final
的變量不能被修改。被聲明為final
的類的方法自動(dòng)聲明為final
,但是實(shí)例變量并不是final
。
3. 多態(tài)
3.1 多態(tài)的概念
多態(tài)是同一個(gè)行為具有多個(gè)不同表現(xiàn)形式或形態(tài)的能力。
多態(tài)就是同一個(gè)接口,使用不同的實(shí)例而執(zhí)行不同操作,如圖所示:
多態(tài)性是對(duì)象多種表現(xiàn)形式的體現(xiàn)。
同一個(gè)事件發(fā)生在不同的對(duì)象上會(huì)產(chǎn)生不同的結(jié)果。
3.2 多態(tài)的優(yōu)點(diǎn)
- 消除類型之間的耦合關(guān)系
- 可替換性
- 可擴(kuò)充性
- 接口性
- 靈活性
- 簡(jiǎn)化性
3.3 多態(tài)存在的三個(gè)必要條件
-
繼承
-
重寫
重寫:子類對(duì)父類的允許訪問(wèn)的方法的實(shí)現(xiàn)過(guò)程進(jìn)行重新編寫,返回值和形參都不能改變。即外殼不變,核心重寫。
重寫的好處:在于子類可以根據(jù)需要,定義特定于自己的行為。也就是說(shuō)子類能夠根據(jù)需要實(shí)現(xiàn)父類的方法。
class Animal { public void eat() { System.out.println("正在吃..."); } } class Dog extends Animal { public void eat() { System.out.println("狗正在吃狗糧..."); } } class Bird extends Animal { public void eat() { System.out.println("鳥(niǎo)正在吃鳥(niǎo)糧..."); } } public class Test1 { public static void fun(Animal animal) { animal.eat(); } public static void main(String[] args) { Dog dog = new Dog(); fun(dog); Bird bird = new Bird(); fun(bird); } } // 運(yùn)行結(jié)果 狗正在吃狗糧... 鳥(niǎo)正在吃鳥(niǎo)糧...
重寫(覆蓋)的規(guī)則:
- 方法名相同
- 參數(shù)列表相同【順序、個(gè)數(shù)、類型】
- 返回值相同
-
父類引用指向子類對(duì)象
比如:
Animal dog = new Dog();
當(dāng)使用多態(tài)方式調(diào)用方法時(shí),首先檢查父類中是否有該方法,如果沒(méi)有,則編譯錯(cuò)誤;如果有,再去調(diào)用子類的同名方法。
多態(tài)的好處:可以使程序有良好的擴(kuò)展,并可以對(duì)所有類的對(duì)象進(jìn)行通用處理。
以下是多態(tài)的例子:
abstract class Animal {
abstract void eat();
}
class Cat extends Animal {
public void eat() {
System.out.println("吃魚(yú)");
}
public void work() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("吃骨頭");
}
public void work() {
System.out.println("看家");
}
}
// 測(cè)試類
public class Test {
public static void show(Animal a) {
a.eat();
// 類型判斷
if (a instanceof Cat) { // 貓做的事情
Cat c = (Cat)a;
c.work();
} else if (a instanceof Dog) { // 狗做的事情
Dog c = (Dog)a;
c.work();
}
}
public static void main(String[] args) {
show(new Cat()); // 以 Cat 對(duì)象調(diào)用 show 方法
show(new Dog()); // 以 Dog 對(duì)象調(diào)用 show 方法
Animal a = new Cat(); // 向上轉(zhuǎn)型: 子類對(duì)象 -> 父類對(duì)象
a.eat(); // 調(diào)用的是 Cat 的 eat
Cat c = (Cat)a; // 向下轉(zhuǎn)型: 父類對(duì)象 -> 子類對(duì)象
c.work(); // 調(diào)用的是 Cat 的 work
}
}
// 運(yùn)行結(jié)果
吃魚(yú)
抓老鼠
吃骨頭
看家
吃魚(yú)
抓老鼠
3.4 instanceof 關(guān)鍵字
Java中可以使用instanceof
關(guān)鍵字判斷對(duì)象是否是某個(gè)類的實(shí)例,語(yǔ)法格式如下:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-789535.html
對(duì)象 instanceof 類
在上述格式中,如果對(duì)象是指定類的實(shí)例對(duì)象,則返回true
,否則返回false
。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-789535.html
class Animal {
public String name;
public int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public void eat() {
System.out.println(this.name + "正在吃...");
}
}
class Dog extends Animal {
public String color;
public Dog(String name, int age,String color) {
super(name,age);
this.color = color;
}
public void eat() {
System.out.println(this.name + "正在吃狗糧...");
}
public void barks() {
System.out.println(this.name + "正在旺旺叫...");
}
}
class Bird extends Animal {
public Bird(String name, int age) {
super(name, age);
}
public void eat() {
System.out.println(this.name + "正在吃鳥(niǎo)糧...");
}
public void fly() {
System.out.println(this.name + "正在飛...");
}
}
public class Test1 {
public static void main(String[] args) {
Animal animal1 = new Dog("旺財(cái)",10,"黃色");
if (animal1 instanceof Bird){ // 判斷 dog對(duì)象是否是Bird類的實(shí)例 如果是則實(shí)例化對(duì)象,否則打印hell
Bird bird2 = (Bird)animal1;
bird2.fly();
}else {
System.out.println("hell");
}
}
}
到了這里,關(guān)于【Java SE語(yǔ)法篇】8.面向?qū)ο笕筇卣鳌庋b、繼承和多態(tài)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!