天天看點

黑馬程式——JAVA繼承,學習進度加快(黑馬我來了之六)

---------------------- android教育訓練、java教育訓練、期待與您交流! ----------------------

繼承

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

2.讓類與類之間産生了關系,有了這個關系,才有了多态的特性;

注意:千萬不要為了擷取其他類的功能,簡化代碼而繼承;

必須是類與類之間有所屬關系才可以繼承,所屬關系 is a。

java語言中,java隻支援單繼承,不支援多繼承。因為多繼承容易帶來安全隐患:當多個父類(也叫超類)中定義了相同功能,當功能内容不同時,子類對象不确定要運作哪一個。但是java保留了這種機制,并用另一種展現形式來完成表示,這種展現形式叫做“多實作”。

java支援多層繼承。也就是一個繼承體系。

3.如何使用一個繼承體系中的功能呢?

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

在具體調用時,要建立最子類的對象,為什麼呢?

1.因為有可能父類不能建立對象;

2.建立子類對象可以使用更多的功能,包括基本的也包括特有的。

簡單說就是:查閱父類功能,建立子類對象使用功能。

子、父類中變量、函數、構造函數的特點

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

1.變量

如果子類中出現非私有的同名成員變量時,子類要通路本類中的變量用this,子類要通路父類中的同名變量,用super,如果子類沒有與父類同名的變量,通路父類中的變量時也可以用:this.父類變量。

super的使用和this的使用幾乎一緻。

this代表本類對象的引用。

super代表父類(超類)對象的引用。

2.函數

當子類出現與父類一模一樣的函數時,如果子類對象調用該函數,會運作子類中該函數的類容,如同父類的函數被覆寫一樣。這種情況叫做覆寫(也叫重寫)。

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

子類覆寫父類,必須保證子類權限大于等于父類權限才可以覆寫,否則編譯失敗。(但是父類權限如果是私有的話,子類就無法知道父類的相同函數功能,進而無法實作覆寫。),

靜态隻能覆寫靜态。

到目前學了public、private、預設權限(就是沒有public、private),預設權限的權限大小介于public和private之間。

記住:

1.重載隻看同名函數的參數清單;

2.(覆寫)重寫要求子父類方法要一模一樣(包括傳回值類型等)。

3.構造函數

super();用于調用父類的空參數構造函數,

如果要調用父類中的有參數構造函數的話,調用格式就是super(參數1,參數2,…);

this();語句調用本類的空參數構造函數。

在對子類對象進行初始化時,父類的構造函數也會運作。那是因為子類的構造函數中預設第一行有一條隐式的語句super();而且子類中所有的構造函數預設第一行都有super();

為什麼子類一定要通路父類中的構造函數:

因為父類中的資料子類可以直接擷取,是以子類對象在建立時,需要先檢視父類是如何對這些資料進行初始化的。是以子類在對象初始化時,要先通路以下父類中的構造函數。

如果要通路父類中指定的構造函數,可以通過手動定義super語句的方式來指定(即super(參數1,參數2,…),調用格式跟this關鍵字在構造函數間的調用方法一樣)。

還有就是super()語句也要求必須定義在子類構造函數的第一行(實體位置上的第一行,不能說平行什麼的)。

子類的執行個體化過程

子類的所有構造函數預設都會通路父類中空參數的構造函數。因為子類中每一個構造函數内的第一行都有一句隐式的super()語句。

當父類中沒有空參數的構造函數時,子類必須手動通過super或者this語句形式來指定要通路父類中的構造函數。

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

Final關鍵字

final : 最終。作為一個修飾符,

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

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

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

4,被final修飾的變量是一個常量隻能指派一次,既可以修飾成員變量,有可以修飾局部變量。

當在描述事物時,一些資料的出現值是固定的,那麼這時為了增強閱讀性,都給這些值起個名字。友善于閱讀。

而這個值不需要改變,是以加上final修飾。作為常量:常量的書寫規範所有字母都大寫,如果由多個單詞組成。

單詞間通過_連接配接。

5,内部類定義在類中的局部位置上時,隻能通路該局部被final修飾的局部變量。

抽象類:

當多個類中出現相同功能,但是功能主題不同,這時可以進行向上抽取,但是隻抽取功能定義,也就是函數名(),而不抽取功能主體。

“抽取”:是通過分析問題的共性内容完成的,不是通過提取相同代碼實作的。

“抽象”:是強迫子類去做覆寫的一種方式。

特點:

1, 抽象方法一定定義在抽象類中,并且,抽象類中也可以有非抽象的方法;甚至抽象類中可以沒有抽象的方法,此種情況下,這個抽象類的功能隻有一個,就是不允許該類執行個體化。

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

3,抽象類不可以用new建立對象,因為調用抽象方法沒意義。

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

抽象類和一般類沒有太大不同,該如何描述事物,就如何描述事物,隻不過,該事物出現了一些看不懂的内容

這些不确定的部分,也是事物的功能,隻是具體實作的方式不一樣,是以需要明确出現,但是無法定義主體。

通過抽象方法來表示。

抽象類比一般類多了抽象函數,不可執行個體化。

抽象類或者接口為什麼不能建立對象?

當這個類中有了抽象方法,作為類的成員存在,那麼這個類如果建立對象,再去調用這個沒有方法主體的抽象方法,

是沒有任何意義的

故此,抽象方法也要存放在抽象類中。并且這個類不能建立對象,因為聲明了抽象的類,說明類當中有抽象方法,

你不能建立一個你看不懂,而且調用函數無意義的類的對象。

abstract 關鍵字,和哪些關鍵字不能共存。

final:被final修飾的類不能有子類。而被abstract修飾的類一定是一個父類。

private: 抽象類中的私有的抽象方法,不被子類所知,就無法被複寫。而抽象方法出現的就是需要被複寫。

static:如果static可以修飾抽象方法,那麼連對象都省了,直接類名調用就可以了。可是抽象方法運作沒意義。

抽象類中是否有構造函數?

有,抽象類是一個父類,要給子類提供執行個體的初始化。

abstract class Student //當類中出現了抽象方法時候,這個類也必須聲明為抽象類,在class前加上abstract

{

abstract void study(); //向上抽取相同功能,但是功能主題不同。去掉了方法主體大括号“{}”,(此處差別于有方法體

//abstract void study1(); 聲明了另一個抽象函數; 并且用abstract關鍵字說明

}

class BaseStudent extends Student

{

void study()

{

System.out.println("base study");

}

//abstract void study1(); 如果BaseStudent類中沒有覆寫study1的抽象方法,那麼這個BaseStudent類也成為了抽象類

//void study1(){} 此語句實作了對Student抽象類中抽象方法study1的“空複寫”

}

class AdvStudent extends Student

{

void study()

{

System.out.println("adv study");

}

}

class AbstractDemo

{

public static void main(String[] args) 

{

//new Student(); //建立了一個抽象類的對象,編譯失敗:“Student是抽象的,無法對其執行個體化”

new BaseStudent().study();

}

}

模版方法設計模式思路:

在定義功能時,功能的一部分是确定的,但是有一部分是不确定,而确定的部分在使用不确定的部分,

那麼這時就将不确定的部分暴露出去。由該類的子類去完成。

示例:

abstract class GetTime

{

public final void getTime()

{

long start = System.currentTimeMillis();

runcode();

long end = System.currentTimeMillis();

System.out.println("毫秒:"+(end-start));

}

public abstract void runcode();

}

class SubTime extends GetTime

{

public void runcode()

{

for(int x=0; x<4000; x++)

{

System.out.print(x);

}

}

}

class TemplateDemo

{

public static void main(String[] args) 

{

//GetTime gt = new GetTime();

SubTime gt = new SubTime();

gt.getTime();

}

}

接口

接口:初期了解,可以認為是一個特殊的抽象類,當抽象類中的方法都是抽象的,那麼該類可以通過接口的形式來表示。

class用于定義類

interface 用于定義接口。

接口定義時,格式特點:

1,接口中常見定義:常量,抽象方法。

2,接口中的成員都有固定修飾符。

常量:public static final

方法:public abstract 

記住:接口中的成員都是public的。隻要定義了接口,它的修飾符就都是固定的,少寫哪個,系統會自動預設補充。

接口:是不可以建立對象的,因為有抽象方法。

需要被子類實作,子類對接口中的抽象方法全都覆寫後,子類才可以執行個體化。否則子類是一個抽象類。

接口可以被類多實作,也是對多繼承不支援的轉換形式。java支援多實作。

類與接口之間是實作關系,而且類可以繼承一個類的同時實作多個接口;接口與接口之間可以有多繼承的關系。

interface Inter

public static final int NUM=3;//全局,靜态,最終。。。。全局常量

public abstract void show();

}

interface InterA 

{

public abstract void show();

}

class Demo

{

public void function(){}

}

class Test extends Demo implements Inter,InterA 

//一個類在繼承一個父類的同時也可以實作一個或多個接口,先繼承在實作可以擴充這個類的功能。

{

public void show(){} //隻要有方法體就實作了覆寫。接口的權限比較特殊

//接口裡面的方法都是公有的,是以要覆寫其中的方法,必須聲明的函數權利為public

//而抽象類不是,抽象類中的方法權限可以單獨設定,而接口都是固定的。

}

interface A

{

void methodA();

}

interface B extends A //接口與接口之間是繼承關系。extends

{

void methodB();

}

interface C extends B //且接口之間存在多繼承,如果B沒有繼承A的話

//C可以直接繼承A和B。 interface C extends B,A 接口的多繼承是因為接口中的抽象方法都沒有方法體

{ //但是在多繼承時候,繼承的兩個或多個接口中不能有同名卻不同類型的函數。

//(因為在執行個體建立對象時,對象調用該函數時會出錯,不知道該調用哪一個) 

void methodC();

}

class D implements C //D若要建立對象的話必須覆寫ABC中的三個方法

public void methodA(){}

public void methodC(){}

public void methodB(){}

}

class InterfaceDemo

{

public static void main(String[] args) 

{ Test t = new Test(); //用實作接口的類建立一個對象

System.out.println(t.NUM); //對象調用成員

System.out.println(Test.NUM); //類名直接調用成員

System.out.println(Inter.NUM); //接口名調用成員。編譯完成後,接口也會生成一個位元組碼class檔案。

//t.NUM = 4; 這個語句是錯誤的,這三個語句中任何一個都不能對NUM指派。

---------------------- android教育訓練、java教育訓練、期待與您交流! ----------------------