1.面向對象編程思想(封裝繼承多態接口)

封裝:

1.定義:隱藏對象的屬性和實現細節,僅對外公開接口,控制在程序中屬性的讀和修改的訪問級別。

2.封裝的目的是:增強安全性和簡化編程,使用者不必瞭解具體的實現細節,而只是要通過外部接口,一特定的訪問權限來使用類的成員。

3.封裝的基本要求是:把所有的屬性私有化,對每個屬性提供getter和setter方法,如果有一個帶參的構造函數的話,那一定要寫一個不帶參的構造函數。在開發的時候經常要對已經編寫的類進行測試,所以在有的時候還有重寫toString方法,但這不是必須的。


繼承:

1.目的:實現代碼的複用。

2.介紹:當兩個類具有相同的特徵(屬性)和行爲(方法)時,可以將相同的部分抽取出來放到一個類中作爲父類,其它兩個類繼承這個父類。繼承後子類自動擁有了父類的屬性和方法,但特別注意的是,父類的私有屬性和構造方法並不能被繼承。另外子類可以寫自己特有的屬性和方法,目的是實現功能的擴展,子類也可以複寫父類的方法即方法的重寫。子類不能繼承父類中訪問權限爲private的成員變量和方法。子類可以重寫父類的方法,及命名與父類同名的成員變量。有時候我們需要這樣的需求:我們需要將某些事物儘可能地對這個世界隱藏,但是仍然允許子類的成員來訪問它們。這個時候就需要使用到protected








多態:

1.概念:相同的事物,調用其相同的方法,參數也相同時,但表現的行爲卻不同。


2. Java實現多態有三個必要條件:繼承、重寫、向上轉型。

         繼承:在多態中必須存在有繼承關係的子類和父類。

         重寫:子類對父類中某些方法進行重新定義,在調用這些方法時就會調用子類的方法。

         向上轉型:在多態中需要將子類的引用賦給父類對象,只有這樣該引用才能夠具備技能調用父類的方法和子類的方法。

      只有滿足了上述三個條件,我們才能夠在同一個繼承結構中使用統一的邏輯實現代碼處理不同的對象,從而達到執行不同的行爲。


3.多態的實現方式:


(1)基於繼承實現的多態

      基於繼承的實現機制主要表現在父類和繼承該父類的一個或多個子類對某些方法的重寫,多個子類對同一方法的重寫可以表現出不同的行爲。


(2)基於接口實現的多態

      繼承是通過重寫父類的同一方法的幾個不同子類來體現的,那麼就可就是通過實現接口並覆蓋接口中同一方法的幾不同的類體現的。

      在接口的多態中,指向接口的引用必須是指定這實現了該接口的一個類的實例程序,在運行時,根據對象引用的實際類型來執行對應的方法。

      繼承都是單繼承,只能爲一組相關的類提供一致的服務接口。但是接口可以是多繼承多實現,它能夠利用一組相關或者不相關的接口進行組合與擴充,能夠對外提供一致的服務接口。所以它相對於繼承來說有更好的靈活性。


4.多態性主要表現在如下兩個方面:


(1)方法重載.通常指在同一個類中,相同的方法名對應着不同的方法實現,但是方法的參數不同.

(2)成員覆蓋.通常指在不同類(父類和子類)中,允許有相同的變量名,但是數據類型不同;也允許有相同的方法名,但是對應的方法實現不同.

5.多態的好處:程序的可擴展性及可維護性增強。


抽象:

1.介紹:在面向對象的概念中,我們知道所有的對象都是通過類來描繪的,但是並不是所有的類都是用來描繪對象的,如果一個類中沒有包含足夠的信息來描繪一個具體的對象,這樣的類就是抽象類。抽象類往往用來表徵我們在對問題領域進行分析、 設計中得出的抽象概念,是對一系列看上去不同,但是本質上相同的具體概念的抽象,我們不能把它們實例化(拿不出一個具體的東西)所以稱之爲抽象


  比如:我們要描述“水果”,它就是一個抽象,它有質量、體積等一些共性(水果有質量),但又缺乏特性(蘋果、橘子都是水果,它們有自己的特性),我們拿不出唯一一種能代表水果的東西(因爲蘋果、橘子都不能代表水果),可用抽象類來描述它,所以抽象類是不能夠實例化的。當我們用某個類來具體描述“蘋果”時,這個類就可以繼承描述“水果”的抽象類,我們都知道“蘋果”是一種“水果”。


2.抽象方法:被abstract修飾的方法是抽象方法,抽象方法沒有方法體。修飾符 abstract 返回值類型 函數名();抽象方法的修飾符只能用public或者protected或者沒有修飾,不能被final,static,private修飾

(1)、類即使不包含抽象方法,也可以定義成抽象類。
(2)、類中含有抽象方法的類一定要定義成抽象類。
(3)、抽象類中字段的定義和子類的訪問與一般類沒有變化。
(4)、擴展抽象類有兩種方法,第一種是在子類中定義部分抽象方法或者抽象方法不定義,這樣子類也必須定義成抽象類,第二種是定義全部的抽象方法,這樣子類就可以不定義成抽象的了。
(5)、抽象類不能被實例化,但是可以定義一個抽象類的對象變量,這個變量可以引用非抽象子類的對象。
(6)、抽象類中包含有構造方法,也可以顯式書寫構造方法,構造方法在實例化子類的對象中調用。


接口與抽象類的區別:


不同點:
1、接口可以多實現,而抽象類只能單繼承
2、抽象類可以有非抽象的方法和構造方法、變量,但是接口只能有抽象方法,靜態常量。
3、抽象類和子類具有父子關係,子類能擁有父類中一些屬性。接口雖然某個類實現一個接口,但是由於接口中的變量都爲靜態常量,不存在繼承關係。


相同點:
1、無論接口還是抽象類,都無法直接實例化,其自身實例化需要靠實現類或子類來實現。
2、接口和抽象類都必須實現其中的所有方法

抽象類(abstract class)的定義方式如下: 


public abstract class AbstractClass             //裏面至少有一個抽象方法
{
   public int t;  //普通數據成員
   public abstract void method1();   //抽象方法,抽象類的子類在類中必須實現抽象類中的抽象方法
   public abstract void method2(); 
   public void method3();   //非抽象方法
   public int method4();
   publi int method4 (){
        …… //抽象類中可以賦予非抽象方法方法的默認行爲,即方法的具體實現
   }

       public void method3(){
        …… //抽象類中可以賦予非抽象方法方法的默認行爲,即方法的具體實現
   } 

}

 

接口(interface)的定義方式如下: 


public interface Interface

   static final int i;  //接口中不能有普通數據成員,只能夠有靜態的不能被修改的數據成員,static表示全局,final表示不可修改,可以不用static final 修飾,會隱式的聲明爲static和final
   

   public void method1();  //接口中的方法一定是抽象方法,所以不用abstract修飾
   

   public void method2();  //接口中不能賦予方法的默認行爲,即不能有方法的具體實現
}

1、一個接口可以被多個類實現,一個類也可以實現多個接口。
2、接口中所有的定義的字段默認都是public static final 的屬性,寫和不寫沒有區別。
3、接口中的方法都是抽象的方法,並且抽象的方法默認都是public abstract修飾的,不能用其他的修飾符修飾,可以不寫。
4、接口中沒有構造方法
5、接口不是類,尤其不能使用new運算符實例化一個接口。但是可以聲明接口的變量,這個變量可以指向實現了此接口的子類。

簡言之抽象類是一種功能不全的類,接口只是一個抽象方法聲明和靜態不能被修改的數據的集合,兩者都不能被實例化。


  從某種意義上說,接口是一種特殊形式的抽象類,在java語言中抽象類表示的是一種繼承關係,一個類只能繼承繼承一個抽象類,而一個類卻可以實現多個接口。在許多情況下,接口確實可以代替抽象類,如果你不需要刻意表達屬性上的繼承的話。

 super的用法:

1.     子類的構造函數如果要引用super的話,必須把super放在函數的首位.

class Base {

    Base() {

       System.out.println("Base");

    }

}

 

public class Checket extends Base {

    Checket() {

       super();//調用父類的構造方法,一定要放在方法的首個語句

       System.out.println("Checket");

    }

 

    public static void main(String argv[]) {

       Checket c = new Checket();

    }

}

          如果想用super繼承父類構造的方法,但是沒有放在第一行的話,那麼在super之前的語句,肯定是爲了滿足自己想要完成某些行爲的語句,但是又用了super繼承父類的構造方法。那麼以前所做的修改就都回到以前了,就是說又成了父類的構造方法了。

 

2.       在java中,有時還會遇到子類中的成員變量或方法與超類(有時也稱父類)中的成員變量或方法同名。因爲子類中的成員變量或方法名優先級高,所以子類中的同名成員變量或方法就隱藏了超類的成員變量或方法,但是我們如果想要使用超類中的這個成員變量或方法,就需要用到super.

 class Country {

    String name;

 

    void value() {

       name = "China";

    }

}

 

class City extends Country {

    String name;

 

    void value() {

    name = "Hefei";

    super.value();//不調用此方法時,super.name返回的是父類的成員變量的值null

       System.out.println(name);

       System.out.println(super.name);

    }

 

    public static void main(String[] args) {

       City c=new City();

       c.value();

       }

}

         爲了在子類中引用父類中的成員變量name和方法value(),在代碼中使用了super、super.name和super.value(),若不調用super.value()時,super.name返回父類成員變量默認值null,調用此方法時,super.value()方法把成員變量name賦值爲China,再利用super.name調用父類的成員變量的值。

     另外,要注意的是super.name調用的是成員變量的值,

class Country {

    String name="xianfan";

 

    String value(String name) {

       name = "China";

       return name;

    }

}

 

class City extends Country {

    String name;

 

    String value(String name) {

    name = "Hefei";

super.value("失敗");//不調用此方法時,super.name返回的是父類的成員變量的值null

       System.out.println(name);

       System.out.println(super.name);

       return name;

    }

 

    public static void main(String[] args) {

       City c=new City();

       c.value("成功");

    }

}

    結果爲:Hefei

xianfan

     此時,super.name返回的值是父類成員變量的值xianfan,而此時的super.value()方法是不起作用的。

 

3.用super直接傳遞參數:

  class Person {

    public static void prt(String s) {

       System.out.println(s);

    }

 

    Person() {

       prt("A Person.");

    }

 

    Person(String name) {

       prt("A person name is:" + name);

    }

}

 

public class Chinese extends Person {

    Chinese() {

       super(); // 調用父類構造函數(1)

       prt("A chinese.");// (4)

    }

 

    Chinese(String name) {

       super(name);// 調用父類具有相同形參的構造函數(2)

       prt("his name is:" + name);

    }

 

    Chinese(String name, int age) {

       this(name);// 調用當前具有相同形參的構造函數(3)

       prt("his age is:" + age);

    }

 

    public static void main(String[] args) {

       Chinese cn = new Chinese();

       cn = new Chinese("kevin");

       cn = new Chinese("kevin", 22);

    }

}

      結果爲:A Person.

A chinese.

A person name is:kevin

his name is:kevin

A person name is:kevin

his name is:kevin

his age is:22

          在這段程序中,this和super不再是像以前那樣用“.”連接一個方法或成員,而是直接在其後跟上適當的參數,因此它的意義也就有了變化。super後加參數的是用來調用父類中具有相同形式的構造函數,如1和2處。this後加參數則調用的是當前具有相同參數的構造函數,如3處。當然,在Chinese的各個重載構造函數中,this和super在一般方法中的各種用法也仍可使用,比如4處,你可以將它替換爲“this.prt”(因爲它繼承了父類中的那個方法)或者是“super.prt”(因爲它是父類中的方法且可被子類訪問),它照樣可以正確運行。但這樣似乎就有點畫蛇添足的味道了。


 this的用法:“this是指向對象本身的一個指針”


說明在什麼情況下需要用到this


        第一、通過this調用另一個構造方法,用發是this(參數列表),這個僅僅在類的構造方法中,別的地方不能這麼用。


        第二、函數參數或者函數中的局部變量和成員變量同名的情況下,成員變量被屏蔽,此時要訪問成員變量則需要用“this.成員變量名”的方式來引用成員變量。當然,在沒有同名的情況下,可以直接用成員變量的名字,而不用this


        第三、在函數中,需要引用該函所屬類的當前對象時候,直接用this。


super和this的異同:

       1)super(參數):調用基類中的某一個構造函數(應該爲構造函數中的第一條語句) 

       2)this(參數):調用本類中另一種形成的構造函數(應該爲構造函數中的第一條語句)
       3)super: 它引用當前對象的直接父類中的成員(用來訪問直接父類中被隱藏的父類中成員數據或函數,基類與派生類中有相同成員定義時如:super.變量名    super.成員函數據名(實參)

      4)this:它代表當前對象名(在程序中易產生二義性之處,應使用this來指明當前對象;如果函數的形參與類中的成員數據同名,這時需用this來指明成員變量名)

 

      5)調用super()必須寫在子類構造方法的第一行,否則編譯不通過。每個子類構造方法的第一條語句,都是隱含地調用super(),如果父類沒有這種形式的構造函數,那麼在編譯的時候就會報錯。

      6)super()和this()類似,區別是,super()從子類中調用父類的構造方法,this()在同一類內調用其它方法。

   7)super()和this()均需放在構造方法內第一行。

   8)儘管可以用this調用一個構造器,但卻不能調用兩個。

   9)this和super不能同時出現在一個構造函數裏面,因爲this必然會調用其它的構造函數,其它的構造函數必然也會有super語句的存在,所以在同一個構造函數裏面有相同的語句,就失去了語句的意義,編譯器也不會通過。

 10)this()和super()都指的是對象,所以,均不可以在static環境中使用。包括:static變量,static方法,static語句塊。

 11)從本質上講,this是一個指向本對象的指針, 然而super是一個Java關鍵字。


以下是關於子類父類的構造方法的注意事項:


       

   轉載自http://blog.csdn.net/qq_22118507/article/details/51422591



發佈了9 篇原創文章 · 獲贊 133 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章