封裝
把客觀事物封裝成抽象的類,并且類可以把自己的數(shù)據(jù)和方法只讓可信的類或者對象操作,對不可信的進行信息隱藏。封裝是面向?qū)ο蟮奶卣髦?,是對象和類概念的主要特性?/p>
通俗地說,一個類就是一個封裝了數(shù)據(jù)以及操作這些數(shù)據(jù)的代碼的邏輯實體。在一個對象內(nèi)部,某些代碼或某些數(shù)據(jù)可以是私有的,不能被外界訪問。
通過這種方式,對象對內(nèi)部數(shù)據(jù)提供了不同級別的保護,以防止程序中無關(guān)的部分意外的改變或錯誤地使用了對象的私有部分。但是如果?個類沒有提供給外界訪問的?法,那么這個類也沒有什么意義了。
我們來看一個常見的 類,比如:Student
public class Student implements Serializable {
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
將對象中的成員變量進行私有化,外部程序是無法訪問的。對外提供了訪問的方式,就是set和get方法。
而對于這樣一個實體對象,外部程序只有賦值和獲取值的權(quán)限,是無法對內(nèi)部進行修改
繼承
繼承 就是子類繼承父類的特征和行為,使得子類對象(實例)具有父類的實例域和方法,或子類從父類繼承方法,使得子類具有父類相同的行為。
在 Java 中通過 extends 關(guān)鍵字可以申明一個類是從另外一個類繼承而來的,一般形式如下:
class 父類 {
}
class 子類 extends 父類 {
}
繼承概念的實現(xiàn)方式有二類:實現(xiàn)繼承
與接口繼承
。
實現(xiàn)繼承是指直接使用基類的屬性和方法而無需額外編碼的能力
接口繼承是指僅使用屬性和方法的名稱、但是子類必須提供實現(xiàn)的能力
一般我們繼承基本類和抽象類用 extends 關(guān)鍵字,實現(xiàn)接口類的繼承用 implements 關(guān)鍵字。
注意點:
通過繼承創(chuàng)建的新類稱為“子類”或“派生類”,被繼承的類稱為“基類”、“父類”或“超類”。
繼承的過程,就是從一般到特殊的過程。要實現(xiàn)繼承,可以通過“繼承”(Inheritance)和“組合”(Composition)來實現(xiàn)。
子類可以擁有父類的屬性和方法。
子類可以擁有自己的屬性和方法, 即?類可以對?類進?擴展。
子類可以重寫覆蓋父類的方法。
JAVA 只支持單繼承 ,即一個子類只允許有一個父類,但是可以實現(xiàn)多級繼承,及子類擁有唯一的父類,而父類還可以再繼承。
使用 implements
關(guān)鍵字可以變相的使java具有多繼承
的特性,使用范圍為類繼承接口的情況,可以同時繼承多個接口(接口跟接口之間采用逗號分隔)。
# implements 關(guān)鍵字
public interface A {
public void eat();
public void sleep();
}
public interface B {
public void show();
}
public class C implements A,B {
}
值得留意的是:關(guān)于父類私有屬性和私有方法的繼承 的討論
這個網(wǎng)上 有大量的爭論,我這邊以Java官方文檔為準(zhǔn):
With the use of the extends keyword, the subclasses will be able to inherit all the properties of the superclass except for the private properties of the superclass.
子類不能繼承父類的 私有屬性 (事實
),但是如果子類中公有的方法影響到了父類私有屬性,那么私有屬性是能夠被子類使用的。
官方文檔 明確說明:private和final不被繼承,但從內(nèi)存的角度看的話:父類private屬性是會存在于子類對象中的。
通過繼承的方法(比如,public方法)可以訪問到父類的private屬性
如果子類中存在與父類private方法簽名相同的方法,其實相當(dāng)于覆蓋
個人覺得文章里的一句話很贊,我們不可能完全繼承父母的一切(如性格等),但是父母的一些無法繼承的東西卻仍會深刻的影響著我們。
多態(tài)
同一個行為具有多個不同表現(xiàn)形式或形態(tài)的能力就是 多態(tài) 。網(wǎng)上的爭論很多,筆者個人認同網(wǎng)上的這個觀點:重載也是多態(tài)的一種表現(xiàn),不過多態(tài)主要指運行時多態(tài)
Java 多態(tài)可以分為 重載式多態(tài)
和重寫式多態(tài)
-
重載式多態(tài)
,也叫編譯時多態(tài)
。編譯時多態(tài)是靜態(tài)的,主要是指方法的重載
,它是根據(jù)參數(shù)列表的不同來區(qū)分不同的方法。通過編譯之后會變成兩個不同的方法,在運行時談不上多態(tài)。也就是說這種多態(tài)再編譯時已經(jīng)確定好了。-
重寫式多態(tài)
,也叫運行時多態(tài)
。運行時多態(tài)是動態(tài)的,主要指繼承父類和實現(xiàn)接口時,可使用父類引用指向子類對象
實現(xiàn)。 這個就是大家通常所說的多態(tài)性 。這種多態(tài)通過
動態(tài)綁定(dynamic binding)
技術(shù)來實現(xiàn),是指在執(zhí)行期間判斷所引用對象的實際類型,根據(jù)其實際的類型調(diào)用其相應(yīng)的方法。也就是說,只有程序運行起來,你才知道調(diào)用的是哪個子類的方法。這種多態(tài)可通過函數(shù)的重寫以及向上轉(zhuǎn)型
來實現(xiàn)。
多態(tài)存在的三個必要條件:
繼承
重寫
父類引用指向子類對象:Parent p = new Child();
我們一起來看個例子,仔細品讀代碼,就明白了:
@SpringBootTest
class Demo2021ApplicationTests {
class Animal {
public void eat(){
System.out.println("動物吃飯!");
}
public void work(){
System.out.println("動物可以幫助人類干活!");
}
}
class Cat extends Animal {
public void eat() {
System.out.println("吃魚");
}
public void sleep() {
System.out.println("貓會睡懶覺");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("吃骨頭");
}
}
@Test
void contextLoads() {
//part1
Cat cat_ = new Cat();
cat_.eat();
cat_.sleep();
cat_.work();
//part2
Animal cat=new Cat();
cat.eat();
cat.work();
cat.sleep();//此處編譯會報錯。
Animal dog=new Dog();
dog.eat();//結(jié)果為:吃骨頭。此處調(diào)用子類的同名方法。
//part3
//如果想要調(diào)用父類中沒有的方法,則要向下轉(zhuǎn)型,這個非常像"強轉(zhuǎn)"
Cat cat222 = (Cat)cat; // 向下轉(zhuǎn)型(注意,如果是(Cat)dog 則會報錯)
cat222.sleep(); //結(jié)果為:貓會睡懶覺。 可以調(diào)用 Cat 的 sleep()
}
}
-
數(shù)據(jù)
+關(guān)注
關(guān)注
8文章
7077瀏覽量
89161 -
封裝
+關(guān)注
關(guān)注
126文章
7937瀏覽量
143083 -
代碼
+關(guān)注
關(guān)注
30文章
4798瀏覽量
68725
發(fā)布評論請先 登錄
相關(guān)推薦
評論