封裝
把客觀事物封裝成抽象的類,并且類可以把自己的數據和方法只讓可信的類或者對象操作,對不可信的進行信息隱藏。封裝是面向對象的特征之一,是對象和類概念的主要特性。
通俗地說,一個類就是一個封裝了數據以及操作這些數據的代碼的邏輯實體。在一個對象內部,某些代碼或某些數據可以是私有的,不能被外界訪問。
通過這種方式,對象對內部數據提供了不同級別的保護,以防止程序中無關的部分意外的改變或錯誤地使用了對象的私有部分。但是如果?個類沒有提供給外界訪問的?法,那么這個類也沒有什么意義了。
我們來看一個常見的 類,比如: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方法。
而對于這樣一個實體對象,外部程序只有賦值和獲取值的權限,是無法對內部進行修改
繼承
繼承 就是子類繼承父類的特征和行為,使得子類對象(實例)具有父類的實例域和方法,或子類從父類繼承方法,使得子類具有父類相同的行為。
在 Java 中通過 extends 關鍵字可以申明一個類是從另外一個類繼承而來的,一般形式如下:
class 父類 {
}
class 子類 extends 父類 {
}
繼承概念的實現方式有二類:實現繼承
與接口繼承
。
實現繼承是指直接使用基類的屬性和方法而無需額外編碼的能力
接口繼承是指僅使用屬性和方法的名稱、但是子類必須提供實現的能力
一般我們繼承基本類和抽象類用 extends 關鍵字,實現接口類的繼承用 implements 關鍵字。
注意點:
通過繼承創建的新類稱為“子類”或“派生類”,被繼承的類稱為“基類”、“父類”或“超類”。
繼承的過程,就是從一般到特殊的過程。要實現繼承,可以通過“繼承”(Inheritance)和“組合”(Composition)來實現。
子類可以擁有父類的屬性和方法。
子類可以擁有自己的屬性和方法, 即?類可以對?類進?擴展。
子類可以重寫覆蓋父類的方法。
JAVA 只支持單繼承 ,即一個子類只允許有一個父類,但是可以實現多級繼承,及子類擁有唯一的父類,而父類還可以再繼承。
使用 implements
關鍵字可以變相的使java具有多繼承
的特性,使用范圍為類繼承接口的情況,可以同時繼承多個接口(接口跟接口之間采用逗號分隔)。
# implements 關鍵字
public interface A {
public void eat();
public void sleep();
}
public interface B {
public void show();
}
public class C implements A,B {
}
值得留意的是:關于父類私有屬性和私有方法的繼承 的討論
這個網上 有大量的爭論,我這邊以Java官方文檔為準:
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不被繼承,但從內存的角度看的話:父類private屬性是會存在于子類對象中的。
通過繼承的方法(比如,public方法)可以訪問到父類的private屬性
如果子類中存在與父類private方法簽名相同的方法,其實相當于覆蓋
個人覺得文章里的一句話很贊,我們不可能完全繼承父母的一切(如性格等),但是父母的一些無法繼承的東西卻仍會深刻的影響著我們。
多態
同一個行為具有多個不同表現形式或形態的能力就是 多態 。網上的爭論很多,筆者個人認同網上的這個觀點:重載也是多態的一種表現,不過多態主要指運行時多態
Java 多態可以分為 重載式多態
和重寫式多態
-
重載式多態
,也叫編譯時多態
。編譯時多態是靜態的,主要是指方法的重載
,它是根據參數列表的不同來區分不同的方法。通過編譯之后會變成兩個不同的方法,在運行時談不上多態。也就是說這種多態再編譯時已經確定好了。-
重寫式多態
,也叫運行時多態
。運行時多態是動態的,主要指繼承父類和實現接口時,可使用父類引用指向子類對象
實現。 這個就是大家通常所說的多態性 。這種多態通過
動態綁定(dynamic binding)
技術來實現,是指在執行期間判斷所引用對象的實際類型,根據其實際的類型調用其相應的方法。也就是說,只有程序運行起來,你才知道調用的是哪個子類的方法。這種多態可通過函數的重寫以及向上轉型
來實現。
多態存在的三個必要條件:
繼承
重寫
父類引用指向子類對象: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();//結果為:吃骨頭。此處調用子類的同名方法。
//part3
//如果想要調用父類中沒有的方法,則要向下轉型,這個非常像"強轉"
Cat cat222 = (Cat)cat; // 向下轉型(注意,如果是(Cat)dog 則會報錯)
cat222.sleep(); //結果為:貓會睡懶覺。 可以調用 Cat 的 sleep()
}
}
-
數據
+關注
關注
8文章
7128瀏覽量
89365 -
封裝
+關注
關注
127文章
7982瀏覽量
143243 -
代碼
+關注
關注
30文章
4820瀏覽量
68881
發布評論請先 登錄
相關推薦
評論