面向對象之繼承

 

//繼承的概述

 

類用來描述事物。

 

將學生和工人的共性描述提取出來,單獨進行描述,只要讓學生和工人與單獨描述的這個類有關係,就可以了。——就是對具體對象抽取共性而得到的類進行再抽取。

 

繼承就是利用這種類中的共性提煉出一個父類(也叫基類或超類),原來的類就是子類。

用關鍵字extends。

 

繼承的作用:

1、提高了代碼的複用性;

2、讓類與類之間產生了關係,有了這個關係,纔有了多態的特性。

 

注意,千萬不要爲了獲取其他類的功能,簡化代碼而繼承,必須是有類與類之間有所屬關係纔可以繼承,所屬關係叫做is a。要用繼承,必須要先保證類與類之間有所屬關係。

 

父類中的內容子類中都具備,就可以表示有繼承,否則就不應該有繼承。

如果用不了繼承的多類,可以對他們進行單獨再進行抽取出一個具有共性的類來,這樣纔可以進行繼承。

 

理論上應該是先有父類,後再有子類。雖然是從子類中抽取的。用生活中例子去理解唄。

 

java語言中,java只支持單繼承,不支持多繼承。因爲多繼承容易帶來安全隱患。當多個父類中定義了相同功能,但功能內容不同時,子類對象不確定要運行哪一個。

 

c++是可以多繼承的,java優化了,讓java好學已用,但是java仍保留了這種機制,對其進行改良,並用另一種體現形式來完成表示,——多實現。

不過java支持多層繼承,也就是一個繼承體系。子承父,父承祖等。是底層不斷向上抽取而來的。

抽取時一定要明白誰是共性,誰是特性的。

 

當繼承關係稍有複雜時,如何使用一個繼承體系中的功能比較快呢?

想要使用體系時,先查閱體系中父類的描述,因爲父類中定義的是該體系中的共性功能,通過了解共性功能就可以知道該體系的基本功能。那麼這個體系就可以已經基本使用了。

在具體調用時,要創建最子類的對象,爲什麼呢?一是因爲有可能父類不能創建對象,而是創建子類對象可以使用更多的功能,包括基本的,也包括特有的。

簡單一句話,查閱父類功能,創建子類對象使用功能。

java當中一個孩子只有一個父親,不可以有多個父親。

 

//繼承代碼體現

 

子父類出現後,類中成員的特點:

類中成員:1、變量。2、函數、3、構造函數。

關鍵字:super,表示本類對象的引用,this表示子類對象的引用。

 

在方法區中,有非靜態區和靜態區。

 

1、變量

如果子類中出現非私有的同名成員變量時,子類要訪問本類中的變量,用this,子類要訪問父類中的同名變量是,用super。

super的使用和this的使用幾乎一致,this代表的是本類對象的引用,super代表的是父類對象的引用。

 

2、函數

函數的一個新的特性,覆蓋,或者叫重寫。

當子類出現和父類一模一樣的函數時,當子類對象調用該函數時,會運行子類函數的內容,如同父類的函數被覆蓋一樣,這種情況是函數的另一個特性:重寫(覆蓋)。

這種叫法只說是種形象說法,父類的方法其實還是在內存中,只是沒有被運行而已。

這種情況以後在設計中會用的比較多。

當子類繼承父類,沿襲了父類的功能到子類中,但是子類雖具備該功能,但是功能的內容,卻和父類不一致,這時沒有必要定義新功能,而是使用覆蓋特性,保留父類的功能定義,並重寫功能內容。

這種方式有利於功能擴展。是在沿襲父類功能,定義之類特有內容。

對手機來電顯示進行舉例

經驗之流:修改以往的源碼絕對是災難。所以初次寫的時候,一定把代碼寫好一點,方便以後擴展。

爲了提高程序的擴展性,我可以使用函數的複寫的特性來提高程序的擴展性,我不改你,我繼承你。

注意:

1、子類覆蓋父類,必須保證子類權限要大於等於父類權限纔可以覆蓋,否則編譯失敗;

2、靜態只能覆蓋靜態;

3、重載只看同名函數的參數列表,覆蓋是子父類方法要一模一樣,包括返回值類型。

 

三種權限:public,默認權限,private。順序由大到小。默認權限在public和private之間。

 

3、構造函數

子父類函數不能覆蓋,因爲至少名稱是不一樣的。

但是子類會把父類的功能繼承下來。

 

在對子類對象進行初始化時,父類的構造函數也會運行,那是因爲子類的構造函數默認第一行有一天隱式的語句super();這個語句會訪問父類中的空參數構造函數,而且子類中所有的構造函數默認第一行都是super()。

當父類的參數不是空參數時,子類就必須要制定對父類功能的指定參數。

 

爲什麼子類一定要訪問父類中的構造函數。

因爲父類中的數據子類可以直接獲取,所以子類對象在建立時需要先查看父類是如何對這些數據進行初始化的,所以子類在對象初始化時,要先訪問一下父類中的構造函數。如果要訪問父類中制定的構造函數,可以通過手動的定義super語句的方式來指定。

 

注意:     super語句必須一定要放在子類的構造函數的第一行。

 

結論:——子類的實例化過程

子類中所有的構造函數默認都會訪問父類中空參數的構造函數,因爲子類每一個構造函數的第一行都有一句隱式的suprer(),。當父類中沒有空參數的構造函數時,子類必須手動通過super或者this語句形式來制定訪問父類中的構造函數。

當然子類的構造函數的第一行也可以手動指定this語句來訪問本類中的構造函數,子類中至少有一個構造函數會訪問父類中的構造函數。。

super語句和this語句只能放在第一行。因爲初始化動作要先做。

 

這個要明確一點的是,繼承是隻繼承的是屬性和功能行爲,而不是數據,如果需要數據就要引用一次。空參數的功能也是一個功能,因爲這個是共享的,不是特例,所以就可以繼承。始終明白一點,繼承,繼承的是共性的部分,獨特的部分是無法繼承的。

如果父類中的某一個功能或者屬性時已經被賦予新的數值,那麼子類在繼承時就要對這個屬性進行賦值,因爲這個屬性已經錯過了初始化了,那麼子類是無法接收到初始化,就必須要先定義一下其取值。

 

java中所有類的父類就是上帝——Object。

 

//final關鍵字:最終,作爲一個修飾符的特點:

1、可以修飾類,函數,變量。

2、被final修飾的類不可以被繼承。裏面的功能不可以複寫的。可以避免被繼承,被子類複寫功能。

3、被final修飾的方法不可以被複寫。

4、被final修飾的變量是一個常量,只能賦值一次,既可以修飾成員變量,又可以修飾局部變量。

5、內部類定義在類中的局部位置上時,只能訪問該局部被final修飾的局部變量。

         當在描述事物時,一些數據的出現值是固定的,那麼這是爲了增強閱讀性,都給這些值起一個名字方便於閱讀。而這個值不需要改變,所以加final修飾。作爲常量,常量的書寫規範是所有字母都大寫,如果由多個單詞組成,那麼單詞間通過下劃線連接。

 

繼承有一個弊端就是打破了封裝性。

 

以後寫代碼,對於常量,即使只出現一次,最好起一個名字,這樣閱讀性會比較好。寫代碼,閱讀性很重要。

 

final,強制和嚴謹的故事。

 

//繼承(下)

 

函數分兩部分,函數聲明和函數主體。

 

當多個類中,出現了相同功能,但是功能主體不同,也可以進行向上抽取,這是隻抽取功能定義,不抽取功能主體。

對於完全看不懂的方法用關鍵字 abstract 修飾,標示看不懂。。

 

類的成員(變量和函數)

實例化就是對象化 建立對象。

抽象方法必須要存放在抽象類中。不要去創建對象。

抽象:就是看不懂,籠統。

 

抽象類的特點:

1、抽象方法一定在抽象類中。

2、抽象方法和抽象類都必須被abstract關鍵字修飾。

3、抽象類不可以用new創建對象,因爲調用抽象方法沒有意義。

4、抽象類中的抽象方法要被使用,必須要由子類複寫所有的抽象方法後,建立子類對象調用,如果子類只覆蓋了部分抽象方法,那麼該子類還是一個抽象類,就必須要加抽象修飾符。

 

所謂抽象不是從代碼抽取,而是通過分析問題抽取得來的。

 

父類裏定義了基本的功能需求,主體部分由子類去實現。

 

抽象可以讓子類強制附上一些功能。具體功能怎麼實現,沒有要求。

 

抽象類裏面,既可以有抽象方法,也可以有非抽象方法。

 

抽象類和一般類沒有太大的不同,該如何描述事物,就如何描述事物,只不過該事物中出現了一些看不懂的東西,這些不確定的部分也是該事物的功能,需要明確出來,無法定義主體。

通常通過抽象方法來表示。

 

抽象類比一般類多了抽象函數,即時在類中可以定義抽象方法,。但是抽象類不可以實例化。

 

抽象只能定義類和方法。

 

抽象類中可以不定義抽象方法,這樣做僅僅是不讓該類建立對象。

 

沒必要建立對象的事物,直接抽象化就可以了。

 

練習,

1、假如我們在開發一個系統時需要對員工進行建模,員工包含3個屬性,姓名,工號和工資,經歷也是員工,。。。。。。。。。。。。。。。。。。第92視頻。

 

建模就是數據模型。

2、需求:獲取一段程序運行的時間。

 

當代碼完成優化後,就可以解決這類問題了。

 

這種方式,叫做模版方法設計模式。解決問題的一種非常好的模式。

 

什麼是模版方法呢?

其實就是在定義功能時,功能的一部分是確定的,但是有一部分是不確定的,而確定的部分在使用不確定的部分,那麼這時就將不確定的部分暴露出去,由該類的子類去完成。

 

提高了擴展性,提高了複用性。

 

模版方法一般抽樣類是很有可能的,但是不一定就是抽象的類。

如,有默認的操作方式,就不一定是抽象的類了。你可以去改更好的方法去。

 

函數用來封裝代碼的。

 

//接口。

 

抽象類裏面可以定義抽象方法,也可以定義非抽象方法。

如果抽象類裏面全都是抽象類裏面的方法全部都是抽象的,這時我們可以把他表現成另一種表現形式——接口。

我們可以這麼來形象的過度理解接口這個概念,但是原因不是這樣的。

初期理解,可以認爲是一個特殊的類,當抽象的方法都是抽象的時候,那麼該類以通過接口的形式來表示,用interface的形式來表示;

class用於定義類,interface用於定義接口。

 

接口定義時,格式特點:

1、接口中常見的定義:常量,抽象方法;

2、接口中的成員都有固定的修飾符:

         常量:publicstatic  final

         方法:publicabstract

 

記住:接口中的成員都是public。

寫了interface裏面的成員都有固定的修飾符,有固定的寫法,權限,修飾符,等都是已經規定好了的。少寫哪個就會自動補哪個。與抽象類不同,抽象類可以自己定義。

 

interface inter

         publicstatic  final NUM x=8;

         publicabstract void show();

 

類與類是繼承關係,而類與接口關係是實現關係;關鍵字 implements。。

 

接口是不能創建對象的,因爲都是抽象方法,所以要用一個子類來實現他。只有當子類對接口中的抽象方法全部覆蓋後後子類纔可以實例化。否則子類也是一個抽象類。

 

如果一個類實現了一個接口,而裏面主體內容爲空,那麼這個類就是抽象類了,把接口的內容全部繼承了。

 

class文件是java的運行文件。因此interface接口編譯的文件也是class格式;

 

接口可以被類多實現。一個類可以同時實現多個接口。即只可以有一個父親,但是可以有多個師傅。

java不支持多繼承,但用另一個方式體現就是多實現。

 

不支持多繼承的原因是因爲父類當中的方法可能會有重複,導致子類在繼承調用的時候會產生問題。

多繼承的方法都是方法體,而多實現裏面繼承的不是方法主體,沒有主體,可以由子類任意定義。

 

一個類在繼承一個類的同時,還可以進行實現多個接口。可以增加自己的功能的。

 

先繼承再實現,可以擴展類的功能。

 

接口與接口之間也可以有關係,即繼承關係。

 

接口之間可以存在多繼承。因爲都沒有方法體,所以就不會有衝突。

但是要注意多繼承的幾個接口中都存在同名方法,那麼這些方法不可以是不同的返回值類型,否則不可以多繼承。因爲被實現後無法確認返回值類型

 

接口要被實例化,就必須要強制被實現才行。

 

//接口的特點

 

暴露的規則、功能的擴展,降低了耦合性。

模塊式開發,就是降低了彼此耦合性。

 

可以用於體系以外的功能上的擴展,擴展其他內容的內容。

 

繼承是所屬於is,接口是擴展like

 

接口用來擴展功能的,最後由子類去實現。

 

基本功能定義在類中,擴展功能定義在接口中。基本功能,額外功能。

繼承就是在體系中發展,接口是在繼承體系外擴展的功能。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章