1. 程式人生 > >面向物件基礎學習心得

面向物件基礎學習心得

一、類與物件

類是用來對一組具有相同特性事物的描述,而物件就是類的例項,類用來描述物件,就像一座大樓與樓的設計圖的關係,蓋成一座大樓需要一張設計圖來確定這座樓有多高,有多大,一層有幾個房間等。萬物皆物件。
例如:

//一個描述人的類
public class Person {
    private String name;  //人的姓名
    private int age;     //人的年齡
    private String sex ;   //人的性別
    public void spaek() {
        System.out.println("說話");
    }
}

上面的程式碼,是一個關於人的類, 類中描述了一個人的屬性如姓名,年齡;還有人的一個動作說話,可以說,通過這個類,我們就能簡單的得到一個‘人’。

Person people1  = new Person(); //java中通過new關鍵字可以建立一個物件。
people1.speak(); // 通過物件可以呼叫該物件的speak方法。

建立一個物件後就可以呼叫其中的成員變數和方法,要注意成員變數的修飾符,public(在所有的類中都能訪問),private(只能在自身類中訪問,也不能在子類中訪問),protected(只能被自身類,子類和同一包中的類訪問),一般常用的就這三個。在上述程式碼中,呼叫了speak方法,其修飾符public,說明可以任意類中的訪問,而name,age屬性,都是私有的private,只能在本類中訪問,如果需要訪問,我們可以在Person類設定return方法來返回,這樣可以保護類中的資料,起到封裝的特性,如:

public String getName(){
    return this.name;
}

二、構造方法

構造方法就是對物件的初始化,就是在new物件時,使物件當出現時就自帶有一些屬性值,比如說一個人,剛出生是父母一般都會起好名字,那麼我們為什麼不在建立物件時就給對像的名字賦值呢?這就需要構造方法。

public class Person {
    private String name;
    protected int age;
    //構造方法,需要傳入名字。
    public Person(String name) {
        this.name = name;
    }

    public
void spaek() { System.out.println("說話"); } public String getName(){ return this.name; } }

構造方法是與類同名,公共的,沒有返回值的方法,不用使用者呼叫,會在建立物件是自動呼叫。

Person people1 = new Person("小王");
people1.getName(); //呼叫people1的getName方法得到name的值  此時name的值同過構造方法的賦值,為“小王”。

三、 重構

上面我們講解了構造方法,那麼問題來了,如果一個人一出生還沒有起好名字,那怎麼辦呢?這就需要說到方法的重構了。就是方法名稱一樣,返回值一樣,就是方法的傳參不一樣。建立物件是根據傳入引數的個數。型別的不同,來呼叫不同的構造方法。不止是構造方法,成員方法也能重構(注意:重構時的引數要麼要在個數上不同,要麼要在傳入引數的型別上不同)。

public class Person {
    private String name;
    protected int age;
    public Person() {   //沒有引數的構造方法
        this.name = "無名";
    }
    public Person(String name) {
        this.name = name;
    }

    public void spaek() {
        System.out.println("說話");
    }
    public String getName(){
        return this.name;
    }
}

當我們呼叫時,可以傳入不同的引數來建立物件。

        Person people1 = new Person("小王");  //建立一個名字為小王的人,呼叫有參構造方法。
        Person people2 = new Person();   //建立一個沒有名稱的人,呼叫無參構造方法
        System.out.println(people1.getName()); // 輸出為  小王
        System.out.println(people2.getName()  //輸出為  無名

四、封裝

封裝、繼承、多型是面向物件的三大特性,現在我們來說封裝, 封裝就是每個物件都包含他能進行操作所需要的所有資訊,把這些資訊包裝在類中,這樣就實現了封裝。

封裝有很多好處,第一、良好的封裝能夠減少耦合,第二、類內部的實現可以自由的修改。

類的封裝就好比一座房子,裡面擺放了精美的傢俱,如果沒有圍牆,那房子內的物品任何人都可以看或者改動,由於有了圍牆(封裝),房屋內的物品就不會被外人動了,但是如果沒有門窗,那麼房子就成了一個鐵盒子,就算裡面的東西再怎麼豪華,再怎麼精美,人不能住進去,也沒用。所以要有門窗,使主人能夠住進來。就像剛才的那個Person類,其中的name屬性是私有的,不能夠在類外訪問,我們加了個getName()方法,是我們能夠訪問到name 的值,這就是封裝物件暴露在外的屬性和方法。

五、繼承

繼承就是子類繼承父類 ,會繼承父類的非private的成員變數和成員方法,子類也能擁有屬於自及的成員變數和成員方法,並且能夠重寫父類的成員方法。
例如:人是一種總稱,但是人有分為中國人,美國人,德國人等,各個不同國家的人擁有相同的屬性,如姓名,性別,年齡等,那麼我們可以使各個國家人的類繼承人的類,人類中包括姓名、性別、年齡等一些共有屬性。而各個國家的人類中可以有一些輸入自己的一些行屬性等。

class Person {
    public String name;
    public int age;

    public Person() {
        this.name = "無名";
    }

    public Person(String name) {
        this.name = name;
    }

    public void spaek() {
        System.out.println("說話");
    }

    public void run () {
        System.out.println("跑");
    }
}
//繼承父類
class Chinese extends Person {
    //構造方法,super()呼叫父類的方法
    public Chinese(String name) {
        super(name);
    }
    //子類特有的方法,中國人唱豫劇
    public void sing() {
        System.out.println("豫劇");
    }

}

在上述程式碼中,有Chinese子類繼承了Person父類,(需要說明的是,在子類中的構造方法,如果父類中有構造方法的重構,而父類中沒有無引數的構造方法的宣告,那麼在子類中的構造方法必須指定呼叫那個父類的構造方法,否則,將會出錯。)會擁有父類的所有成員和方法,而在子類中則增加類中國人特有的京劇。如果我們在main函式中new出Chinese的物件,那麼是可以呼叫父類的成員屬性和方法的。

如果之後我們想加入美國人、德國人等,只需要建立相應的類,然後繼承Person類,同樣可以擁有name,age等屬性,以此,提高了程式碼的可讀性、和複用性。

使用繼承是需要注意的是,兩事物A和B之間的關係必須是A包含B,那麼才能讓B繼承A。

六、多型

現在假設要舉行一場跑步運動會。各個國家的熱都要參加,要怎樣才能讓不同國家的人同時賽跑呢,那麼這就用到了多型,多型就是不同的對像可以執行相同的動作,就拿豫劇來說吧,有一位非常出名的老父親,演豫劇演的特別好,他兒子每天跟老父親學習,也學是非常像,有一天,老父親生病了,上不了臺表演,他兒子可以替父親上臺表演,因為他們表演的特別像,再因為在臺上化了妝,觀眾根本認不出來。這就是多型的原理,宣告對像是宣告父類物件,new物件時new出子類物件。

class Person {
    public String name;
    public int age;
    public Person() {
        this.name = "無名";
    }
    public Person(String name) {
        this.name = name;
    }

    public void spaek() {
        System.out.println("說話");
    }

    public void run () {
        System.out.println("跑");
    }
}

class Chinese extends Person {
    public Chinese(String name) {
        super(name);
    }

    public void run(){
        System.out.println("我是中國人"+this.name+",我參加運動會");
    }

    public void sing() {
        System.out.println("豫劇");
    }
}

public class RunSport {
    public static void main(String[] args) {
        Person chinese = new Chinese("小王"); //用父類指向子類物件。
        chinese.run(); // 呼叫子類中重寫後的run方法 ,輸出 "我是中國人小王,我參加運動會"
    }
}

使用多型時要注意 1.子類以父類的身份出現,2. 子類的工作方式以自己的工作方式實現;3. 子類以父類的身份出現時,子類特有的屬性和方法不可以使用(子類中重寫父類的方法可以使用);
下面,我們來運用多型來實現運動會。我們先來增加幾個國家:

//美國人
class American extends Person {
    public American(String name) {
        super(name);
    }

    public void run(){
        System.out.println("我是美國人"+this.name+",我參加運動會");
    }

}

//德國人
class  German extends Person {
    public  German(String name) {
        super(name);
    }

    public void run(){
        System.out.println("我是德國人"+this.name+",我參加運動會");
    }

}

俄羅斯人
class Russians extends Person {
    public Russians(String name) {
        super(name);
    }

    public void run(){
        System.out.println("我是俄羅斯人"+this.name+",我參加運動會");
    }

}

我們用Java中的容器來儲存參賽人員,來實現比賽。

public class RunSport {
    public static void main(String[] args) {
        ArrayList<Person> athletes = new ArrayList<Person>();
        athletes.add (new Chinese("小王"));
        athletes.add (new American("邁克"));
        athletes.add (new German("約翰"));
        athletes.add (new Russians("鮑里斯"));

        for (int i = 0; i < athletes.size(); i++) {
            athletes.get(i).run();
        }
    }
}
/* 執行結果
我是中國人小王,我參加運動會
我是美國人邁克,我參加運動會
我是德國人約翰,我參加運動會
我是俄羅斯人鮑里斯,我參加運動會
*/ 

這就是不同的物件可以執行相同的動作,但要通過他們自己的程式碼實現來執行。

七、抽象類

在上述代發中我們可以發現Person類根本不用例項化,那麼我們就可以把他設為抽象類,抽象類是不能例項化的。把需要重寫的方法設定為抽象方法。

abstract class Person {
    public String name;
    public int age;
    public Person() {
        this.name = "無名";
    }
    public Person(String name) {
        this.name = name;
    }

    //普通方法,可以被繼承,也可被重寫
    public void spaek() {
        System.out.println("說話");
    }
    //抽象方法,在子類中必須重寫
    public abstract void run ();
}

class Chinese extends Person {
    public Chinese(String name) {
        super(name);
    }

    //重寫父類的抽象方法,以自己的方式實現
    public void run(){
        System.out.println("我是中國人"+this.name+",我參加運動會");
    }

}

抽象方法在使用時應該注意:

  1. 抽象類不能例項化
  2. 抽象方法是必須被子類重寫的方法
  3. 如果父類中擁有抽象方法,那麼父類必須被宣告稱抽象類

八、介面

根據上述例子,當一個國家或幾個國家的人擁有特別的功能時怎麼辦呢,有人會說再各自國家的子類中定義各自特殊的方法,但是那樣的話會使程式碼變得雜亂,使用介面是讓使用者和其他開發人員更容易理解他人的程式碼。
接下來我們以我們的國球為例,假設一個人會打乒乓球,那麼我們先要有一個打乒乓球的介面,宣告介面是需要注意,介面中不允許出現任何成員的執行方式,不能宣告無值得成員變數,若定義成員變數是賦初值,那麼這個成員變數會預設宣告為public static final 型別。

interface  PingPong{
    //宣告打乒乓球方法
    public void play();
}

那麼在子類中就需要實現該方法

class Chinese extends Person implements PingPong{
    public Chinese(String name) {
        super(name);
    }

    public void run(){
        System.out.println("我是中國人"+this.name+",我參加運動會");
    }

    public void sing() {
        System.out.println("豫劇");
    }

    //實現介面中方法
    public void play() {
        System.out.println("打乒乓球");
    }
}

有了這個介面,當在出先一個人會打乒乓球時,我們直接讓這個人繼承PingPong類就行了。
現在來說一下介面和抽象類的區別,抽象類可以給出一些成員變數的實現,而介面不能包含有實現,抽象類的抽象成員可被子類部分實現,介面的成員需要需要實現類完全實現。

參考文獻《大話設計模式》程傑著