1. 程式人生 > 實用技巧 >SpringMVC中Model機制

SpringMVC中Model機制

這裡我們定義一個Person的類:

class Person {
    private String name;
    private int age;

    public String getName() {...}
    public void setName(String name) {...}
    public int getAge() {...}
    public void setAge(int age) {...}
}

在定義一個Student類:

class Student {
    private String name;
    private int age;
    private int score;

    public String getName() {...}
    public void setName(String name) {...}
    public int getAge() {...}
    public void setAge(int age) {...}
    public int getScore() { … }
    public void setScore(int score) { … }
}

可以發現,這兩個類中,有很多相同的欄位和方法,那麼我們可不可以在Sutdent類中不用再寫相同的欄位和方法,只寫其特有的屬性和方法呢?

當然可以! 但是,要用到java的 extends關鍵字,他表示繼承。

class Person {
    private String name;
    private int age;

    public String getName() {...}
    public void setName(String name) {...}
    public int getAge() {...}
    public void setAge(int age) {...}
}

class Student extends Person {
    // 不要重複name和age欄位/方法,
    // 只需要定義新增score欄位/方法:
    private int score;

    public int getScore() { … }
    public void setScore(int score) { … }
}

這樣我們就可以自寫需要新增的程式碼。

注意:子類自動獲得了父類的所有欄位,嚴禁定義與父類重名的欄位!

在OOP的術語中,我們把Person稱為超類(super class)、父類(parent class)、基類(base class),把Student稱為子類(subclass),擴充套件類(extended class)。

繼承樹

在編寫父類,person的時候我們並沒有,給person寫extends。它同樣會有一個繼承關係,不過這個關係是java的機制中的預設繼承關係,Java中預設Obect類為所有類的父類。

繼承關係如下:

java只允許一個class繼承一個父類。也就是說在java中的所有繼承關係都是單繼承。一個類有且只有一個父類。object類是特例,它沒有父類。

我們再定義一個別的類時,繼承樹如下:

一個類可以被多個類繼承,但是它只能繼承一個父類。

繼承中的欄位修飾關係和普通的一樣,有 private ,預設,protect和public。但是,繼承中有個特點,就是子類無法訪問父類的private字元或者private方法,

class Person {
    private String name; //私有化欄位
    private int age; //私有化欄位,不能被訪問
}

class Student extends Person {
    public String hello() {
        return "Hello, " + name; // 編譯錯誤:無法訪問name欄位
    }
}

這樣一來 ,繼承的作用就削弱了,如果要訪問欄位,我們可以將private,改成protect。被這個關鍵字修飾的欄位可以被子類訪問。

class Person {
    protected String name;
    protected int age;
}

class Student extends Person {
    public String hello() {
        return "Hello, " + name; // OK!
    }
}

super關鍵字

super關鍵字表示父類(超類)。子類引用父類的欄位時,可以使用super.filedNama。

class Student extends Person {
    public String hello() {
        return "Hello, " + super.name;//這裡可以不用spuer,用this.name 或則 name 也可以,編譯器會自動定位到父類欄位
    }
}

但是,以下的這個時候就必須要用 super關鍵字。

class Person {
    protected String name;
    protected int age;
	//定義個無參的構造方法
     //public Person() { }

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

class Student extends Person {
    protected int score;
	//直接執行會報錯,因為編譯器會自動給子類新增一個  sper();  
    //  super();//但是父類並沒有無參的構造方法,解決辦法可以給父類新增一個無參的構造方法 或者 有suer(name,age);指定呼叫有參構造方法
    public Student(String name, int age, int score) {
        this.score = score;
    }
}
public class Main {
    public static void main(String[] args) {
        Student s = new Student("Xiao Ming", 12, 89);
    }
}
    

可以得出一個結論:如果父類沒有預設的狗雜方法,子類就必須顯示的呼叫super()並且給出引數以便讓編譯器定位到父類的一個合適的構造方法。

這裡也可以看出,子類不會繼承父類的任何狗雜方法,子類預設的構造方法是編譯器自己生成的,不是繼承的。

區分繼承和組合

在使用繼承時,我們要注意邏輯一致性。

class Book {
    protected String name;
    public String getName() {...}
    public void setName(String name) {...}
}

再寫一個繼承類、我們能不能讓子類繼承父類的 nama欄位:

class Student extends Book {
    protected int score;
}

顯然,從邏輯上講,這是不合理的,Student不應該從Book繼承,而應該從Person繼承。

究其原因,是因為StudentPerson的一種,它們是is關係,而Student並不是Book。實際上StudentBook的關係是has關係。

具有has關係不應該使用繼承,而是使用組合,即Student可以持有一個Book例項:

class Student extends Person {
    protected Book book;
    protected int score;
}

因此,繼承是is關係,組合是has關係。