-------------------------ASP.Net+Unity開發、.Net培訓、期待與您交流!--------------------------
面向對象的特徵:封裝、繼承和多態
封裝:即將不需要對外提供的具體的實現細節,來隱藏起來,而僅提供公共訪問方式。如,類是一個封裝體,函數是一個封裝體等。
上次博客已經總結了封裝即類的特點。下面總結繼承和多態。
------------------------------------------------------------------------------
繼承
1、定義:
繼承即爲一個類和另一個類之間的繼承關係。而父類的出現是由子類一級一級的抽取而
獲得的,即父類是子類的共性內容。
2、繼承的好處
第一,提供了代碼的複用性;
第二,讓類與類之間產生了關係,爲面向對象的特點多態提供了前提。
3、繼承的注意事項
繼承不支持多繼承,只繼承單繼承,但支持多層繼承。因爲若一個類可以同時繼承多個父類
則當父類之間出現了相同功能時,子類使用時會不知道該調用哪一個功能。所以java不支持多繼承
但java保留這種機制,並用另一種體現形式--多實現來完成。
4、繼承的特點
第一,繼承用到的關鍵字爲extends
第二,對於一個繼承體系的使用,是查閱父類中的方法,而創建最底層子類的對象。
5、繼承中類的各個成員的特點
------------------------------------------------------------------------------
繼承中類的各個成員的特點
成員變量
1、當父類和子類中有同名的成員變量的定義時,則當子類對象調用時,默認使用的是子類中的成員變量。
要想使用父類的成員變量,則在使用變量的前面加上super。
例子:
class Fu
{
int num=4;
}
class Zi extends Fu
{
int num=5;
void show()
{
System.out.println(num);//此時結果爲5,因爲默認的是this.num
System.out.println(super.num);//結果爲4,即調用的是父類中的變量。
}
}
class BianLiangTest
{
public static void main(String[] args)
{
Zi z=new Zi();
z.show();
}
}
2、this和superthis:表示本類對象。但是本類的對象那麼多,到底代表哪個對象呢?this代表的是調用
它所在的函數的本類對象。
super:表示的是子類的父類的引用。
------------------------------------------------------------------------------
成員函數
1、子類可以直接繼承父類中的函數,也可以根據自己的情況將父類中具有的功能主體自己再重新
寫一次,即出現了子父類間函數的覆蓋現象。
2、覆蓋的特點
第一,父類和子類中功能的定義一樣,但是功能主體不一樣。
第二,當子類對象調用該功能時,會運行子類中的此功能,如同父類的函數被覆蓋一樣。
3、子類函數覆蓋父類函數的條件
子類函數的權限必須大於等於父類函數的權限。
注意,靜態只能覆蓋靜態。
4、由覆蓋而產生的思想
當在原來的功能的前提下再添加新的功能時,並沒有必要去修改原來的功能,而是利用覆蓋
的特點來實現添加功能,並在此新的功能主體中調用原來的功能即可。
例子:
class Tel
{
void show()
{
System.out.println("number");
}
}
class NewTel extends Tel
{
void show()//複寫了父類的相同功能
{
super.show();//調用父類的原有功能
System.out.println("name");//增加新的功能
System.out.println("pic");
}
}
class MethodTest
{
public static void main(String[] args)
{
NewTel nt=new NewTel();
nt.show();
}
}
------------------------------------------------------------------------------構造函數
1、構造函數之間無覆蓋功能。但是子類的構造函數會調用父類的構造函數,利用super語句
子類構造函數之間也可以調用,通過this語句。
2、子類的構造函數中至少有一個構造函數默認的第一行有一條隱式的語句super(),來調用父
類的構造函數。
例子:
class Fu
{
Fu()
{
System.out.println("Fu-----run");
}
}
class Zi extends Fu
{
Zi()
{
//默認有super()
System.out.println("Zi--run");
}
Zi(int num)
{
this();//當子類構造函數的首句是this()語句時,則就沒有默認的super()語句了
System.out.println("Zi-----------num");
}
}
class ConstructorTest
{
public static void main(String[] args)
{
Zi z=new Zi();//最終結果爲Fu-----run
// Zi--run
}
}
3、當父類中無空參數的構造函數時,則子類中必須手寫上一句super(參數)語句,與父類中的構造函數一樣,參數填父類構造函數參數的類型的值。
例子:
class Fu
{
Fu(int x)
{
System.out.println("Fu-----x");
}
}
class Zi extends Fu
{
Zi()
{
//由於父類無無參的構造函數,所以此處手凍的寫上
super(3);
System.out.println("Zi--run");
}
Zi(int num)
{
this();//當子類構造函數的首句是this()語句時,則就沒有默認的super()語句了
System.out.println("Zi-----------num");
}
}
class ConstructorTest
{
public static void main(String[] args)
{
Zi z=new Zi();//最終結果爲Fu-----3
// Zi--run
Zi z2=new Zi(4);//結果爲Fu-----3
//結果爲Zi----------4
}
}
4、this語句和super語句this語句是用於本類構造函數之間的調用。
super語句是用於子類調用父類構造函數。
這兩個語句都必須寫在構造函數的第一行。所以這兩句在構造函數中是不能同時出現的。
5、爲什麼子類的構造函數的首句一定要訪問父類的構造函數的呢?
因爲父類中的數據子類是需要繼承的,那麼子類在創建對象並對對象進行初始化時,應該
先要看看父類中是怎麼對數據進行初始化的。所以子類的構造函數的首句要訪問父類的構造函數。
6、總結
第一,子類的所有的構造函數,默認都會訪問父類中空參數的構造函數,因爲子類每一個構造函數
的首句都有一句隱式的super()語句。
第二,當父類中沒有空參數的構造函數時,子類必須手動通過super語句形式來指定要訪問父類中
的構造函數。
第三,當然,子類中的構造函數第一行也可以手動指定this語句來訪問本類中的構造函數。但是
子類中至少有一個構造函數會訪問父類中的構造函數。
------------------------------------------------------------------------------
抽象類
1、格式:abstract class Student
{
}
2、抽象類的運用
當多個類中出現相同功能,但是功能主體不同,這時可以進行向上抽取,只抽取功能定義
,而不抽取功能主體。這樣將抽取的功能定義就封裝到一個抽象類中。讓子類來具體實現這些
抽象功能。
3、抽象類的特點
第一,抽象方法一定定義在抽象類中;
第二,抽象方法和抽象類都必須被abstract關鍵字修飾;
第三,抽象類不可以創建對象,因爲調用抽象方法沒意義;
第四,抽象類中的方法要被使用,必須由子類複寫起所有的抽象方法後,建立子類對象調用,
如果子類只覆蓋了部分抽象方法,那麼該子類還是一個抽象類。
第五,抽象類中可以有抽象方法,也可以沒有,那麼此抽象類只是爲了不讓創建它的對象。
4、抽象類和一般類的區別
抽象類和一般類沒有太大區別,該怎麼描述事物就怎麼描述事物,只不過該事物出現了一些
看不懂的東西,這些不確定的部分,也是該事物的功能,需要明確出現,但是無法定主體,所以
通過抽象方法來表示。
5、由抽象類而總結出的編程思想:模板方法設計模式
在定義功能時,功能的一部分是確定的,但是有一部分是不確定的,而確定的部分在使用不確定的部分,
那麼這時就將不確定的部分暴露出來,定義爲抽象的,由該類的子類去完成。
例子:
/**
需求:獲取一段程序的運行時間。
步驟:
1.定義一個獲取時間的類
2.類中定義一個函數,用來獲取時間
3.用一個函數單獨用來記錄運行的程序
模板方法設計模式:
定義:在定義功能時,功能的一部分是確定的,但是有一部分是不確定的,
而確定的部分在使用不確定的部分,那麼這時就將不確定的部分暴露
出來(即抽象化),由該類的子類去完成(即在子類中將此方法進行復寫)。
*/
abstract class GetTime
{
public void getTime()
{
long start=System.currentTimeMillis();
runCode();
long end=System.currentTimeMillis();
System.out.println("time="+(end-start));
}
//由於此程序並不確定,所以抽象出來
public abstract void runCode();
}
//此抽象方法由子類來具體實現
class SubTime extends GetTime
{
public void runCode()
{
for (int x=0;x<400 ;x++ )
{
if (x%2==0)
{
System.out.println(x);
}
}
}
}
class GetTimeDemo
{
public static void main(String[] args)
{
SubTime st=new SubTime();
st.getTime();
}
}
------------------------------------------------------------------------------接口
1、接口用interface來定義,並且接口可以看成是程序的功能擴展。
2、接口定義時,格式特點:
第一,接口中常見定義:常量,抽象方法
第二,接口中的成員都有固定修飾符
即:常量:public static final eg:public atatic final int NUM=4;
方法:public abstract eg:public abstract void show();
3、注意接口中的成員都是public的
4、接口是不可以創建對象的,因爲接口中的方法都是抽象的,需要被子類實現,子類對
接口中的抽象方法全都覆蓋後,子類纔可以實例化,否則子類是一個抽象類。
5、接口可以被多實現(即一個類可以實現多個接口),也是對多繼承不支持的補充。
6、接口和抽象類的不同是,抽象類中可以有構造方法,而接口中沒有。
7、類在繼承的基礎上可以多實現。
8、接口和接口之間是實現:extends 並且接口之間可以多繼承。
類與類之間是繼承:extends
類與接口之間是繼承:implements
例如:
interface A
{
}
interface B
{
}
class C
{
}
class D extends C implements A,B
{
}
-------------------------ASP.Net+Unity開發、.Net培訓、期待與您交流!--------------------------