---------------------- 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教育訓練、期待與您交流! ----------------------