Java面向對象之:封裝、繼承、多態

2020-12-23 老夫編程說
Java面向對象之:封裝、繼承、多態

高內聚和低耦合

面向對象的最終目的是要構建強健、安全、高效的項目,也就是要實現項目的高內聚和低耦合:

高內聚:把該模塊的內部數據,功能細節隱藏在模塊內部,不允許外界直接幹預;只能通過公開的接口訪問;低耦合:該模塊只需要給外界暴露少量功能方法;模塊之間相互依賴的程度不高;封裝

什麼是封裝

把對象的狀態和行為看成一個統一的整體,將二者存放在一個獨立的模塊中,比如:類;細節隱藏, 把不想對外公開的實現細節隱藏起來,使用private私有化使其私有化,向外暴露public方法,保證調用者安全訪問,不會出現因為越界導致本不應該出現的問題出現;封裝的好處:

調用者能夠正確、方便地使用系統功能,有效地防止調用者隨意修改系統屬性。把特定的功能封裝起來,提高功能的重用性。降低功能組件之間的耦合性,即使一個模塊的實現細節發生改變,只要保證對外暴露的接口或者方法保持不變,就不會影響到其他調用者。訪問權限修飾符

應封裝的隱藏細節的理念,java提供了訪問權限修飾符來控制調用者的訪問權限,詳情如下:

private:屬於類訪問權限,表示私有的,只能在當前類中訪問,使用private修飾的類、方法、欄位,在』離開當前類的作用域之後,調用者就不能直接訪問。

(預設):其實就是什麼都不寫,其屬於包訪問權限,表示包私有的,調用者的包必須和當前類(使用預設修飾)的包相同才能訪問。

protected:屬於子類訪問權限,表示受保護的,使用private修飾的類、方法、欄位不僅同包中類可以訪問,而且即使不同包,但是如果有繼承關係,也可以訪問。

public:表示全局的公共訪問權限,使用private修飾的類、方法、欄位,在當前項目中任何地方都可以訪問。接口(interface)中的方法默認都是public的。

訪問權限修飾符

一般情況下,類的欄位都使用private修飾;封裝了實現細節的方法,一般也使用private修飾,因為不希望調用者直接訪問其實現細節,而是要通過公開的public方法間接調用。

封裝實例

很少會使用(預設),即使要使用,也僅僅是暴露給同包中的其他類訪問;protected很多時候出現在繼承關係中,父類只希望被子類訪問的欄位和方法時;

繼承

從面向對象的角度上說,繼承是一種從一般到特殊的關係,是一種「is a」的關係,即子類是對父類的拓展,是一種特殊的父類,比如:狗是動物的一種特殊情況,狗屬於動物;在這個例子中,動物是父類,狗是子類,狗繼承了動物的特徵和行為,並在動物的特徵和行為的基礎之上拓展自己的特徵和行為,構成了狗這種特殊的動物。

所以可以基於父類並對其加以拓展,產生新的子類定義,這就是繼承;子類可以通過繼承獲得父類原有的欄位和方法,也可以增加父類所沒有的欄位和方法,更是可以覆寫父類中的允許被子類覆蓋的欄位或者方法。

在Java中使用」extends」關鍵字來表示子類和父類之間的繼承關係;在Java中,類之間的繼承關係只允許單繼承,不允許多繼承,一個類只能有一個直接父類。

繼承語法格式:

繼承語法格式

也就是說一個類只能有一個直接的父類,不能出現類A同時繼承於類B和類C。即便不允許多繼承,但是多重繼承是被允許的。以下是一個多重繼承的例子:

動物有胎生動物和卵生動物之分,胎生動物有老虎,老虎又分華南虎,東北虎,孟加拉虎等。在繼承體系中可以這樣來表示:

華南虎——》老虎——》胎生動物——》動物

多重繼承

最終,華南虎通過多重繼承獲得了老虎、胎生動物、動物的特徵和行為。

繼承的優點:

有效的解決了代碼的重用問題,使代碼拓展更加靈活;通過從繼承關係,可以從始至終完整的體現出一個應用體系,邏輯更加清晰;一般在開發中是先有多個自定義類,再從多個類中寫共同的代碼,抽象生成一個父類,然後子類都繼承於它。使用web框架開發時,也會更多的使用繼承來拓展框架的功能,以適應不同的業務需求。

繼承體系

子類可以繼承父類的哪些成員(根據訪問修飾符來判斷):

父類中使用protected、public修飾的成員;父類和子類在同一個包中,父類中預設修飾符的成員可以被子類繼承;不能繼承的是:

父類中使用private修飾的成員;父類的構造器,子類也不能繼承,因為構造器必須和當前的類名相同,父類的構造器是父類的名稱,子類的構造器是子類的名稱;方法重寫和方法重載

方法重寫(Override):從父類繼承的方法(行為)不符合子類的功能需求,那此時子類就需要重新實現父類的方法,並重寫方法體,以實現子類需求。

方法重寫的原則:一同兩小一大

一同

方法籤名必須相同。 方法籤名= 方法名 + 方法的參數列表,參數類型、參數個數、參數順序都必須一致兩小

子類方法的返回值類型和父類方法的返回類型相同或者是其子類,子類可以返回一個更加具體的子類.子類方法聲明拋出的異常類型和父類方法聲明拋出的異常類型相同或者是其子類,子類方法中聲明拋出的異常小於或等於父類方法聲明拋出異常類型;子類方法可以同時聲明拋出多個屬於父類方法聲明拋出異常類的子類(RuntimeException類型除外,RuntimeException是個特例);

子類異常拋出

一大:

子類方法的訪問權限與父類方法訪問權限相同或者更大;而private方法不能被子類所繼承,也就不會被覆蓋。在重寫方法父類方法時,使用@Override註解修飾方法,若是重寫錯誤,就會報編譯錯誤,是一大開發利器;這裡需要注意的是只有方法會被重寫,欄位則沒有重寫一說。

方法重載(Overload): 在同一個類中,方法名字相同,但是因方法參數列表不同而又不同的實現,這樣的機制稱為方法重載,其實現原則是:兩同一不同,返回值並不計入其中。

兩同:相同類,方法名(只是方法名,不是方法籤名)相同

一不同:方法參數列表不同,包括參數類型、參數個數、參數順序都必須一致

方法重載

方法重載(Overload)和方法重寫(Override)兩者只是名字上比較接近,其本身並沒有關係。

this 關鍵字

this關鍵字表示當前對象,當前對象就是this所在的這個對象。this主要存在於兩個位置:

構造器中: 就表示當前正在創建的對象方法中: 表示方法的調用者對象當一個對象創建之後,JVM會為對象分配一個引用該對象自身的引用:this。this的使用是為了:

解決成員變量和方法參數、局部變量之間的二義性,使用this可以顯式指向成員變量;同類中實例方法間相互調用,雖然此時可以省略不寫,但還是建議不要省略,以提高代碼的可讀性。將this作為參數傳遞給另一個方法;將this作為方法的返回值(鏈式方法編程);構造器重載的互相調用,this([參數])必須寫在構造方法第一行;static不能和this一起使用;因為當字節碼被加載進JVM的時候,static成員就已經存在了,但是此時對象很有可能還沒有被創建,沒有對象也就沒有this。super 關鍵字

在對象中this表示當前對象,而super則表示當前對象的父類對象。在子類初始化過程中會創建子類對象,但在創建子類對象之前,會先創建父類對象;也就是說調用子類構造器之前,在子類構造器中會先調用父類的構造器,如果沒有顯式的調用父類構造器,那麼默認情況下會隱式的調用父類無參數構造器。

super關鍵字用於顯式調用父類方法、構造器和欄位;可以使用super解決子類隱藏了父類的欄位情況;在子類方法中,調用父類被覆蓋的方法;在子類構造器中,調用父類構造器。

class SuperClass {public SuperClass() {}}class SubClass extends SuperClass { public SubClass() { super(); // 調用父類構造器 }}

父類構造器的不可或缺性:

如果父類不存在可以被子類訪問/調用的構造器,則子類就不可能存在。也就是必須要先有父類對象,而後才會有子類對象;如果父類沒有提供無參數構造器,子類就必須顯式地通過super語句去調用父類帶參數的構造器。子類對象在初始化過程中,必須先調用父類構造器,而後再調用子類構造器。繼承中的隱藏

上文中提到了隱藏的概念,繼承中的隱藏表示會忽略一些特徵和方法,比如靜態欄位和靜態方法:

滿足繼承的訪問權限下,隱藏父類靜態方法:若子類定義的靜態方法的籤名和超類中的靜態方法籤名相同,那麼此時就是隱藏父類方法。注意:僅僅是在子類存在和父類一模一樣的靜態方法的情況下。滿足繼承的訪問權限下,隱藏父類欄位:若子類中定義的欄位和父類中的欄位名相同(忽略數據類型),此時是隱藏父類欄位,但是可以通過super訪問被隱藏的欄位。隱藏本類欄位:若本類中的局部變量名和欄位名相同,此時就是隱藏本類欄位,可以通過this訪問被隱藏的欄位。無論是this,還是super,都不能和static一起使用。

Object 類

在Java中除去Object類之外的每一個類都有一個直接或間接的父類:Object類。也就是說除去Object類之外的類都是Object類的直接子類或間接子類。

比如:

class Person {}class Student extends Person{}

此時Student類的直接父類是Person,Person類的直接父類是Object類,Object類是Student類的間接父類。

Object類是Java的基類,Java中的類都是Object的直接或者間接的子類,Object本身是指對象的意思, 它是所有的對象都具有的共同的行為的抽象類,其他類都會直接或者間接繼承於Object類,然後也就擁有了Object類中的方法。

class SuperClass {} 等價於 class SuperClass extends Object {}

Object類的常見方法:

finalize() :當垃圾回收器確定不存在對該對象的更多引用時,也就是垃圾回收器會在回收對象之前,會先調用該方法;該方法我們一般不會調用。getClass() :返回當前對象的真實類型。hashCode(): 返回該對象的哈希碼值,hashCode(哈希碼值)決定了對象再哈希表中的存儲位置,不同對象的存儲位置是不一樣的,所以hashCode也會是不一樣的。equals(Object obj) :用當前對象(this)和參數obj做比較,在Object類中的equals方法,比較對象的內存地址。官方建議:每個類都應該覆蓋equals方法,不要比較內存地址,而是去比較內容數據。toString():表示把一個對象轉換為字符串,列印對象時,調用的就是對象的toString方法,默認情況下列印的是對象的十六進位的hashCode值。 官方建議:應該每個類都應該覆蓋toString,返回我們真正關心的數據。多態

通過上文,講清楚了繼承關係,繼承關係是一種」is a」(是一種)的關係,也就是說子類是父類的一種特殊情況;既然子類是一種特殊的父類,我們是否可以認為子類對象就是父類類型的對象。

考慮以下的代碼:

Animal d = new Dog(); //創建一隻狗對象,類型是動物Animal c = new Cat(); //創建一隻貓對象,類型是動物

這個時候,多態就產生了。我們以下面的代碼為例,詳細解釋什麼是多態:

Animal a = new Dog();

在上例中,對象a具有兩種類型:

編譯類型: 聲明對象變量的類型,Animal;表示把對象看作是什麼類型。運行類型: 對象的真實類型,Dog;運行類型--->對象的真實類型。編譯類型必須是運行類型的父類或與之相同,當編譯類型和運行類型不同的時候,多態就產生了。所謂多態是指對象具有多種形態,對象可以存在不同的形式:

Animal a = null;a = new Dog(); //a此時表示Dog類型的形態a = new Cat(); //a此時表示Cat類型的形態

多態可以是類和類之間的繼承關係,也可以是接口和實現類間的實現關係,一般情況下指的都是接口和實現類間的實現關係。

多態的特點:把子類對象賦給父類類型的變量,在運行時期會表現出具體的子類特徵,比如父類類型的變量調用子類的方法。

多態的好處:通過一個例子呈現

需求:給飼養員提供一個餵養動物的方法,用於餵養動物。

如果沒有多態,針對於不同類型的動物,得提供不同的餵養方法。可拓展性差,方法重用性低,不優雅。存在多態:提供統一的餵養方法,大大減輕了飼養員的工作量。從上述例子,不難發現:當把不同的子類對象都當作父類類型來看待,可以屏蔽不同子類對象之間的實現差異,從而寫出通用的代碼達到通用編程,以適應需求的不斷變化。

多態

數據類型轉換

基本數據類型轉換:大和小表示的是可存儲的容量範圍。

自動類型轉換:把小類型的數據賦給大類型的變量:

byte b = 12; byte是1個字節int i = b; int是4個字節強制類型轉換:把大類型的數據賦給小類型的變量。

short s = (short) i ;short是2個字節引用類型的轉換: 引用類型的大和小,指的是父類和子類的關係。

自動類型轉換: 把子類對象賦給父類變量(多態)。

Animal a = new Dog();Object obj = new Dog();

強制類型轉換:把父類類型對象賦給子類類型變量(對象的真實類型是子類類型)。

Animal a = new Dog();Dog d = (Dog)a;

instanceof 運算符

instanceof 運算符: 判斷該對象是否是某一個類的實例。

語法格式:

boolean b = 對象A instanceof 類B; // 判斷 A對象是否是 B類的實例,如果是,返回true.

instanceof運算符:

若對象是類的實例返回true。若對象是類的父類的實例也返回true。組合關係(has a)

在繼承關係中,子類可以繼承到父類中部分的成員,那麼此時子類是可以修改到父類的信息的,此時的繼承關係破壞了封裝,讓子類擁有了本不該具有的功能。那麼這時可以使用」包含關係」(has a)的組合關係。

可以這麼理解組合關係:把另一個類當作屬性來獲取其特徵和行為。

比如:需求是:我想擁有天子的權力;

方式1: 當太子,此時表現的是繼承關係;方式2: 學曹操挾天子以令諸侯,挾持天子,此時是組合/包含關係。思考:如果A類想要得到B的功能行為,如若A類是B類的一種特殊情況,就應該採用繼承來實現,否則使用組合方式。

組合實例

完結。

相關焦點

  • Java面向對象特徵——多態
    多態1.什麼是多態、如何實現面向對象的三大特徵之一:多態多態的定義:某一類事物的多種存在方式(一個對象,兩種形態)上圖代碼所示,在Dog類繼承Animal時,在new對象的時候,對象的引用類型可以為Animal類,父類或者接口的引用指向其子類的對象,這就是多態的實現。
  • Java 中的繼承和多態(深入版)
    面向對象的三大特性:封裝、繼承、多態。在這三個特性中,如果沒有封裝和繼承,也不會有多態。那麼多態實現的途徑和必要條件是什麼呢?以及多態中的重寫和重載在JVM中的表現是怎麼樣?在Java中是如何展現繼承的特性呢?對於子類繼承於父類時,又有什麼限制呢?
  • Java面向對象程序設計之類的封裝
    面向對象的三大特性(前幾天已經介紹過,文末有相關閱讀可以查閱),現在就來看一看面向對象第一大特性——封裝性。那什麼是封裝性呢?可以發現,之前所列舉的程序都是用對象直接訪問類中的屬性,這在面向對象法則中是不允許的。
  • Java面向對象之final、abstract抽象、和變量生命周期
    Java面向對象之final、abstract抽象、final修飾符final是最終、不可修改的意思, 在Java中它可以修飾非抽象類,非抽象方法和變量只要滿足以下條件就可以考慮把一個類設計成final類:在設計之初就考慮不進入繼承體系的類。出於安全考慮,類的實現細節不允許被拓展和修改。比如:基本數據類型的包裝類就是一個典型的例子。該類不會再被拓展。
  • Java基礎知識學習:Java三大特效之多態!
    1.1 多態的形式多態是繼封裝、繼承之後,面向對象的第三大特性。多態是出現在繼承或者實現關係中的。多態體現的格式:父類類型 變量名 = new 子類/實現類構造器;變量名.方法名();多態的前提:有繼承關係,子類對象是可以賦值給父類類型的變量。例如Animal是一個動物類型,而Cat是一個貓類型。
  • 圖說Java中的OOPs(面向對象編程系統)基本概念
    面向對象編程是一種編程概念,其核心思想是允許用戶創建所需要的對象,然後提供處理這些對象的方法,使用者通過操作對象而獲得運算數據。本文將以簡潔的方式對面向對象編程中的概念進行梳理。1.對象既包含數據又包含對數據進行操作的方法。例如,我們日常生活中能夠體現具體物理事物的鋼筆,電腦桌,顯示器,自行車,玻璃杯等等。3. Inheritance(繼承)繼承是Java中的一種機制,它允許其中一個對象獲取父對象的所有屬性和行為(方法)。他是面向對象編程系統(OOPS)的重要組成部分。Java繼承的思想是可以創建基於現有類的新類。
  • CSharp基礎知識-面向對象
    面向對象面向對象是一個抽象的概念,其本質就是對事物以抽象的方式建立對應的模型。 簡單來講,比如我有一隻鋼筆,那麼我就可以通過分析,可以得到 這隻鋼筆的材第是塑料,品牌是個雜牌 ,裡面裝的墨是黑色的,可以用。
  • 第79p,什麼是多態,多態有什麼特點?
    大家好,我是楊數Tos,這是《從零基礎到大神》系列課程的第79篇文章,第三階段的課程:Python進階知識:類與對象(十);面向對象編程3大特性之多態。一、什麼是多態?多態指的是同一種事物有多種形態;比如:水和冰都是水,人既是人也是動物;多態帶來的特性是可以在不考慮對象具體類型的情況下使用對象;比如:只要是人就一定會說話、吃飯、呼吸,而不用考慮他是老人還是小孩子;多態性帶來的好處在於減少使用者的學習成本;比如:我們考駕駛的時候只需要考汽車駕照就可以了
  • python高手養成記03:面向對象是什麼?網友:能3天掌握一門語言
    本章目錄:1、面向對象書本的話2、面向對象最簡單,快速的理解3、面向對象設計例子面向對象書本的話首先理解一下這幾個概念,OOA,OOD,OOPOOA:面向對象分析OOD:面向對象設計OOP:面向對象編程在基本的程序開發中,基本上也是按照這個順序來做,分析-->設計-->編程。
  • C風格的面向對象編程
    面向對象編程(OOP),最早是C++、java等面向對象語言的一個核心特點,之後發展成了一種編程思想。面向對象編程的主要特點是,把屬性(數據)與方法(函數)按照類型綁定,並按照類型之間的關係分層分模塊設計,通過基類指針和虛函數實現多態。
  • 面向對象編程
    面向對象編程(OOP)對於初學者來說可能是一個很難理解的概念。很多書籍都是從解釋OOP開始,討論三大術語:封裝、繼承和多態性,但是解釋的效果往往讓人失望。本文希望讓程式設計師、數據科學家和python愛好者們更容易理解這個概念。我們去掉所有的行話,通過一些例子來做解說。
  • 多態是什麼 父類如何調用子類的方法(美團面試))
    /01/多態多態(Polymorphism)按字面的意思就是「多種狀態」。在面向對象語言中,接口的多種不同的實現方式即為多態。引用Charlie Calverts對多態的描述——多態性是允許你將父對象設置成為一個或更多的他的子對象相等的技術,賦值之後,父對象就可以根據當前賦值給它的子對象的特性以不同的方式運作(摘自「Delphi4 編程技術內幕」)。簡單的說,就是一句話:允許將子類類型的指針賦值給父類類型的指針。多態性在Object Pascal和C++中都是通過虛函數實現的。
  • 你必須掌握的 21 個 Java 核心技術!
    對象和實例在這方面,開發者需要了解class和instance的概念以及之間的差別, 這是java面向對象特性的一個基礎。面向對象編程的概念這是一個java的核心概念,對於任何java開發者都需要熟練掌握。Java中很多特性或者說知識點都是和java面向對象編程概念相關的。在我的理解,一個好的開發者不僅僅需要了解這些特性(知識點)本身。
  • 「程式設計師之路」17什麼叫多態?
    面向對象三大特性:封裝、繼承和多態。今天學最後一個特性:多態。什麼叫多態呢?按照字面意思理解就是多種形態的意思。同一行為(吃東西),通過不同的事物(兔,貓,狗),可以體現出不同的形態(兔子吃胡蘿蔔,貓吃魚,狗吃肉),這就叫多態。一、多態的格式1.格式說明:父類引用指向子類對象。具體什麼意思呢?
  • 從零開始學Python-Day37-面向對象編程
    OOP–Object Oriented Programming,面向對象編程,是一種程序設計思想。OOP把對象作為程序的基本單元,一個對象包含了數據和操作數據的函數。面向過程的程序設計把電腦程式視為一系列的命令集合,即一組函數的順序執行。
  • 面向對象編程會被拋棄嗎?這五大問題不容忽視
    注意,這僅涵蓋封裝的概念。也就是說,位於對象內部的數據和函數對於外部是不可見的。我們只能通過消息(通常通過 getter 和 setter 函數)與對象的內容進行交互。繼承性和多態性並沒有包含在最初的設計想法中,但是對於現在的面向對象編程而言是必需的。繼承基本上意味著開發者可以定義具有其父類所有屬性的子類。
  • Java基礎面試題簡單總結
    派生類可以從它的基類那裡繼承方法和實例變量,並且類可以修改或增加新的方法使之更適合特殊的需要。封裝:封裝是把過程和數據包圍起來,對數據的訪問只能通過已定義的界面。面向對象計算始於這個基本概念,即現實世界可以被描繪成一系列完全自治、封裝的對象,這些對象通過一個受保護的接口訪問其他對象。多態性:多態性是指允許不同類的對象對同一消息作出響應。多態性包括參數化多態性和包含多態性。
  • C++基礎(2)——封裝(補充)與繼承
    java不香嗎?如果你看到這裡,表示老子就要和C++槓上了,新手入門可以看一看。首先是本地IDE,一開始我用的是visual studio,後來因為vscode插件太好用了,轉換成了vscode,但是初學者建議使用visual studio,因為vscode的頭文件和源文件的連結有點麻煩。
  • 超硬核的Java學習路線指南,看完以後不用再問我怎麼學Java了!
    我們都知道編程技術語言很多,如當下比較火的程式語言就有java,python,javascript,php等語言,而今天我們就來講一講熱門程式語言Java,因為現階段我們的java程序還是很厲害的,不管是大型項目、高並發上億的數據量還是操作小項目,其穩定性,安全性都是數一數二的,非常nice!!
  • 100天python計劃-Day9面向對象進階
    面向對象進階在前面的章節我們已經了解了面向對象的入門知識,知道了如何定義類,如何創建對象以及如何給對象發消息。為了能夠更好的使用面向對象編程思想進行程序開發,我們還需要對Python中的面向對象編程進行更為深入的了解。