黑馬程序員——java第七天:面向對象(繼承、子父類之變量、final、抽象、模板方法、接口)

------- android培訓java培訓、期待與您交流! ---------- 

繼承(extends

繼承的作用:1、提高代碼的複用性。

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

注意:

(1)      千萬不要爲了獲取其他類的功能簡化代碼而繼承,必須是類與類之間有所屬關係纔可以繼承。所屬關係(is a)。

(2)      兩個類有共性沒有所屬關係,可以先建立一個他們共有的屬性的類,讓他們兩個繼承這個類。

(3)      java語言中java只支持單繼承,不支持多繼承。因爲多繼承容易構成安全隱患(當多個父類中定義相同功能,而功能內容不同時子類對象不確定運行哪一個)。

c++中有多繼承,java中沒有多繼承,但是java保留了這種機制,並用另一種體現形式完成表示——多實現!

java支持多層繼承,也就是一個繼承體系,那如何使用一個繼承體系中的功能呢?

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

爲什麼在具體調用時要創建最子類的對象?

1、  有可能父類不能創建對象

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

(查閱父類功能——創建子類對象——使用功能)

聚集關係:(對象與對象、類與類、事物與事物之間的關係不光繼承一種

聚集:誰裏面有誰(has a

聚合:例如球員與球隊的關係。

組合:例如人與心與手的關係(比聚合關係更緊密)。

父子類中變量的特點:

當子類和父類定義了相同的非私有的屬性時默認訪問的是子類的屬性,因爲省略了thisthis.屬性)如果訪問父類的屬性要加supersuper.屬性);

1、  當父類的屬性被私有化了,子類就不能調用了(但是還是被繼承來了)。

2、  this代表本類的引用;super代表父類的引用。

例子:

publicclass ExtendsDemo{

    publicstaticvoid main(String[] args) {

       Zi z=new Zi();

       z.show();

 

    }

 

}

class Fu{

    privateintnum=4;

}

class Zi extends Fu{

    intnum=5;

    void show(){

       System.out.print(num);//若要寫作super.num則語法錯誤。

    }

}


 

 

new Zi();Z.class文件,在加載Z.class文件之前先把Fu.class加載了(沒有父親哪來的孩子)。

子父類中變量的特點—覆蓋(重寫)

父子類中函數的特點:

        當子類出現和父類一模一樣的函數時。當子類對象調用該函數,會運行子類函數內容如同子類覆蓋了子類拿到父類的這個方法一樣(但父類這個方法還存在於內存中)。

什麼時候用到覆蓋:

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

publicclass ExtendsDemo{

    publicstaticvoid main(String[] args) {

       Zi z=new Zi();

       z.speak();

    }

}

class Fu{

    void show(){

       System.out.print("fushow");

    }

    void speak(){

       System.out.print("VB");

    }

}

class Zi extends Fu{

    void speak(){

       System.out.print("java");

    }

    void show(){

       System.out.print("zishow");

    }

}


 

 

注意:1、子類覆蓋父類,必須保證子類權限大於或等於父類的權限,纔可以覆蓋,否則編譯失敗。

2靜態中能覆蓋靜態。

當類前不寫權限修飾詞時爲默認權限,默認權限介於publicprivate之間。

 

publicclass ExtendsDemo{

    publicstaticvoid main(String[] args) {

       Zi z=new Zi();

       z.speak();

    }

}

class Fu{

    void show(){

       System.out.print("fushow");

    }

    privatevoid speak(){       //注意次不叫重寫,因爲父類的函數私有化了

       System.out.print("VB");

    }

}

class Zi extends Fu{

    void speak(){

       System.out.print("java");

    }

    void show(){

       System.out.print("zishow");

    }

}


重載和重寫區別:

        重載:在一個類中只看同名函數的參數列表。

        重寫:子類和父類的方法要一摸一樣(所以構造函數不能重寫)。

子類實例化過程

關於構造函數(子父類)

  

       publicclass ExtendsDemo{

    publicstaticvoid main(String[] args) {

       Zi z=new Zi();

    }

}

class Fu{

    Fu(){

       System.out.println("fu run");

    }

}

class Zi extends Fu{

    Zi(){                       //在子類構造函數的第一句默認有super();調用父類構造函數

       System.out.print("zirun");

    }

}


注意:在對子類對象初始化時,父類的構造函數也會運行,那是因爲子類的構造函數默認第一行有一條隱式的語句——super();調用了父類的構造函數。

    super();會訪問父類中的空參數的構造函數。而且子類中所用的構造函數默認第一行都有super();

    當父類的構造函數是帶參數的時,子類中就必須手動調用父類構造函數。

publicclass ExtendsDemo{

    publicstaticvoid main(String[] args) {

       Zi z=new Zi();

    }

}

class Fu{

    Fu(int a){

       System.out.println("furun"+a);

    }

}

class Zi extends Fu{

Zi(){super(4);                                //在父類構造帶參子類構造函數的第一句要手動super(4);調用父類構造函數

       System.out.print("zirun");

    }

}


 

 

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

         因爲父類中的數據子類可以直接獲取,所以子類對象在建立時,需要先看父類是如何對這

數據進行初始化的。所以子類在對象初始化時要先訪問一下父類中的構造函數。

         如果要訪問父類中指定的構造函數,可以手動定義super語句的方式來指定。

注意:1super語句一定定義在子類構造函數的第一行。

2this語句和super語句在構造函數中不能共存。因爲this語句和super語句都是要放在構造函數的第一行,所以不能共存(不管是默認的還是手動寫的)。

3、在子類中,當構造函數不寫this語句也不寫super語句,默認有空參數的super語句。子類的所有構造函數默認都會訪問父類的空參數的構造函數,因爲子類每一個構造函數內容的第一行都有一句super語句。

4、父類默認也有super語句,因爲Object類是所有類的父類。

關鍵字final

final(最終):作爲一個修飾符。

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

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

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

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

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

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

抽象類(當多個類出現相同功能,但是功能主體不同,這時可以進行向上抽取,只抽取功能定義,而不抽取功能主體。)(抽象;看不懂)。

抽象類的特點:

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

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

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

抽象類中的方法要被使用必須有子類複寫其功能後,建立子類對象調用。如果子類只覆蓋了部分抽象方法那麼該子類還是一個抽象類。

publicclass AbstractDemo{

    publicstaticvoid main(String[] args) {

       //BassStudent z=newBassStudent();        //此處會報錯,因爲抽象類//創建對象無意義

       new AdrStudent().study();

    }

}

abstractclass Student{

    abstractvoid study();

    abstractvoid study1();  

}

abstractclass BassStudent extends Student{      //因爲繼承父類的方法還有study1功能沒有實現所以也是抽象類

    void study(){                      

       System.out.print("bassstudent");

    }

}

class AdrStudentextends Student{

    void study(){                      

       System.out.print("AdrStudent");

    }

    void study1(){}

}


 

 

1、  抽象類和一般類沒什麼太大區別,只不過抽象類中有抽象方法(沒有主體),也可以有非抽象的方法。抽象方法也是該類的功能,需明確出現,但無法定義主體。

2、  抽象類不可以實例化。

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

例子

假如我們在開發一個系統時,需要對員工進行建模,員工包括3個屬性:姓名、工號、以及工資。經理也是員工,除了包含有員工的屬性還有一個獎金屬性,請使用繼承的思想設計出員工類和經理類,要求類中提供必要的方法進行屬性訪問

publicclass question {

    publicstaticvoid main(String[] args) {

       Pro1 p=new Pro1("張三","jisu01",1000);

       p.work();

       System.out.println(p.getName());

       Manager m=new Manager("李四","lisi",3000,4000);

       m.work();

       System.out.println(m.getName());

    }

}

abstractclass Employee1{

    private String name;

    private String id;

    privatedoublepay;

    Employee1(String name,String id,double pay){

       this.name=name;

       this.id=id;

       this.pay=pay;

    }

    publicabstractvoid work();

 

    public String getName() {

       returnname;

    }

}

class Manager extends Employee1{

    privateintbonus;

    Manager(String name,String id,double pay,int bonus){

       super(name,id,pay);

       this.bonus=bonus;

    }

    publicvoid work(){

       System.out.print("managerwork");

    }

}

class Pro1 extends Employee1{

 

    Pro1(String name, String id, double pay) {

       super(name, id, pay);

    }

    publicvoid work(){

       System.out.print("Porwork");

    }

}


 

 

模板方法模式

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

原理:獲取程序開始和結束的時間並相減。獲取時間方法:System.currentTimeMillis();

模板方法:在定義功能時,功能的一部分是確定的,但是有一部分是不確定的,而確定的部分在使用不確定的部分,那麼這時就將不確定的部分暴露出來,由該類的子類去完成

publicclass AbstractDemo{

    publicstaticvoid main(String[] args) {

       SubTime time=new SubTime();

       time.getTime();

    }

}

abstractclass GetTime{

    publicfinalvoid getTime(){

       long start=System.currentTimeMillis();

       runcode();

       long end=System.currentTimeMillis();

       System.out.println("運行時間"+(end-start));

    }

    publicabstractvoid runcode();

}

class SubTime extends GetTime{

    publicvoid runcode(){

       for(int i=0;i<100;i++)          

       System.out.println(i);

    }

    

}


 

 

接口(interface):初步理解可以認爲是一個特殊的抽象類,當抽象類中的方法都是抽象的,那麼該類可以通過接口的形式來表示。

class用來定義類;interface用於定義接口。

接口定義格式:1、接口中常見定義:常量、抽象方法。

3、 接口中的成員都有固定修飾符:常量:publicstatic final

方法publicabstract

4、 記住:接口中的成員屬性都是public的。

注意:

接口內的方法都是抽象的需要被子類重寫實現,所以接口是不能創建對象的。若子類不能全部實例化,那麼這個子類也是一個抽象類。

publicclass InterficeDemo {

    publicstaticvoid main(String[] args) {

       Test1 t=new Test1();

       System.out.println(t.NUM);

       System.out.println(Test1.NUM);//NUM爲靜態的所以可以這樣調用

       System.out.println(Inter.NUM);//這個要記住

    }

}

interface Inter{

    publicstaticfinalintNUM=3;

    publicabstractvoid show();

}

class Test1 implements Inter{

    publicvoid show(){}

}


 

 

特點:1、接口可以被多實現(implements),也是對不支持多繼承的彌補,java支出多實現。

2、一個類在繼承一個類的同時還可以多實現。

<1>接口與接口之間的關係可以是繼承關係(不能是實現);

<2>接口與接口之間可以多實現。

<3>類與類之間的關係可以是繼承(extends)關係(不能是實現);

<4>類與接口之間可以是實現(implements)關係.

注意禁止出現:接口A中有show()方法返回值爲int

                           接口B中也有show()方法放回值爲boolean

                            接口C繼承AB

                            D實現C(不允許AB中有相同的方法返回不同類型的值,因爲返回值衝突)

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

例:

publicclass Temporary {

    publicstaticvoid main(String[] args) {

       ZhangSan zhang=new ZhangSan();

       zhang.sleep();

       zhang.smake();

       zhang.study();

    }

}

abstractclass Student{

    abstractvoid study();

    void sleep(){

       System.out.println("sleep");

    }

}

interface Smokeing{

    void smake();

}

class ZhangSan  extends Student implements Smokeing{

    @Override

    void study() {

       System.out.println("study");       

    }

 

    @Override

    publicvoid smake() {

       System.out.println("smake");       

    }

    

}

------- android培訓java培訓、期待與您交流! ----------詳細請查看:http://edu.csdn.net

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