1. 程式人生 > >《Java程式設計基礎》 第8章手記Part 1

《Java程式設計基礎》 第8章手記Part 1

本章主要內容 Part 1


- 子類的建立
- 在子類中訪問父類的成員
- 覆蓋父類的方法
- ……

本章主要講繼承、抽象類和介面,這篇部落格講的是繼承這一部分。使用實驗的程式碼做例子來說明。

類的繼承

類的繼承是面向物件的程式設計的一個重要特點,通過繼承實現程式碼的複用,被繼承的類稱為父類或超類(superclass),由繼承得到的類稱為子類(subclass)

子類繼承父類成員變數方法,同時可以修改父類的成員變數或重寫父類的方法,還可以新增新的成員變數和方法。

Ps:C語言通過函式實現程式碼複用,但是函式一經寫好,它的功能就已經確定,你修改這個函式會影響到所有已經使用這個函式的程式碼。瞭解這點,你就能理解繼承這種程式碼複用機制的優點——可以修改,並且不會影響之前使用該功能的舊程式碼。

使用繼承來組織、設計系統中的類,可以提高程式的抽象程度,使之更能接近人類的思維方式,同時繼承也能較好的實現程式碼複用,提升程式開發效率,降低維護工作量。

Java中有一個名為java.lang.Object的特殊類,所有的類都是直接或間接繼承得到的。如果沒有指明子類所繼承的父類,則預設繼承這個特殊的類。

子類的建立

子類的建立方法

Java通過關鍵字extends實現繼承,格式如下:

//Java繼承示例
class SubClass extends SuperClass
{
...
}

C#實現繼承的方式則沒有使用任何關鍵字,而是通過英文分號實現的。

//C#繼承示例
public
class SubClass : SuperClass { }

實驗8-1

class PersonB {
    String name;
    int age;

    PersonB() {
        name = "Steve Wang";
        age  = 20;
    }
    PersonB(String name, int age) {
        this.name = name;
        this.age = age;
    }
    void show() {
        System.out.println(name+ " "
+age); } } class StudentB extends PersonB { StudentB() { name = "Zark Berg"; age = 23; } StudentB(String name, int age){ this.name = name; this.age = age; } void show(){ System.out.println(name+ " " +age); } } class Inherite { public static void main(String[] args) { PersonB a = new PersonB("apple",18); StudentB b = new StudentB("pear",16); a.show(); b.show(); } }

說明:

1. 通過extends關鍵字,可將父類的成員繼承給子類,在使用這些繼承過來的成員時,可利用過去的語法即可。
2. Java程式在執行子類的構造方法之前,會先呼叫父類中沒有引數的構造方法,其目的是為了幫助父類繼承自父類的成員做初始化操作。

呼叫父類中特定的構造方法

即使程式中沒有指明子類呼叫父類的構造方法,執行時也會預設代用父類中沒有引數的構造方法。如果父類中有多個構造方法,則使用super關鍵字來呼叫特定的構造方法。this這裡指代的是父類構造方法名稱。

例: super(String a, int b)將呼叫父類中有2個引數,並且第一個是字串型別,第二個是整型的構造方法。

你需要閱讀原書p123頁到p123頁的內容來具體瞭解super及super和this的關係。

在子類中訪問父類的成員
也是使用super關鍵字,格式如下

super.變數名
super.方法名

需要說明的是,父類中的成員必須不是private,才能被子類訪問,建議使用protected,使用public會降低封裝性。

覆蓋

覆蓋(Overriding)的概念與過載類似,都是Java“多型”的實現方法。覆蓋是指在子類中,定義名稱、引數個數和型別均與父類完全相同的方法,用來重寫父類中同名方法的操作。C#的覆蓋是通過虛方法實現的,具體參見之前的博文《C#多型》。

覆蓋父類的方法

實驗8-2

class Animal {
    String name;
    Animal() {
        name = "Animal";
    }
    void play() {
        System.out.println(name);
    }
}

class Bird extends Animal {
    String name;
    Bird() {
        name = "Bird";
    }
    void play() {
        System.out.println(name);
    }
}

class Fish extends Animal {
    Fish() {
        name = "Fish";
    }
    void play() {
        System.out.println(name);
    }
}

class Override {
    public static void main(String[] args) {
        Animal a = new Animal();
        Bird b = new Bird();
        Fish c = new Fish();

        a.play();
        b.play();
        c.play();

        Animal a1 = new Bird();
        Animal a2 = new Fish();

        a1.play();
        a2.play();
    }
}

用父類的物件訪問子類的成員

Java中可以用父類的物件訪問子類的成員,這體現了“父親的行為像兒子,而不是兒子的行為像父親”這種面向物件編的程思想。
注意:
父類的物件訪問子類的成員僅限於“覆蓋”發生時,如果子類沒有覆蓋父類的方法,則不能父類物件不能訪問子類成員。

不可被繼承的成員或最終類

預設情況下所有的成員變數和方法都可以被覆蓋,如果不希望被覆蓋,則需加final關鍵字做宣告。

例:static final double PI = 3.1415926
例:public final void show()

final修飾成員變數,則說明該成員變數是最終量,即常量,程式的其他部分可以訪問但不能修改。

final修飾成員方法,則該方法為最終方法,不能被子類所覆蓋。


知乎:Solo | 微博@從流域到海域