物件導向 01 - 類的成員

December 17, 2020

OOP 學習

  1. JAVA 的 Class 與 Class 中的成員
  1. 以下特徵

Class 與 Object

Class 為對事物的描述,一種抽象概念。Object 實際存在的個體,也稱實例(instance)。

以下為 Class 範例,當中會包含屬性與行為

class Person {
    // 屬性
    String name;
    int age;
    // 行為
    public void eat() {
        System.out.println("吃飯");
    }
    public void sleep() {
        System.out.println("睡覺");
    }
    public void say(String language) {
        System.out.println("我使用" + language + "說話");
    }
}

當把人這抽象的事物給描述好後,要建立一個實際的實例。

    public static void main(String[] args) {
        Person human = new Person(); // 實例化
        // 調用其屬性與方法 
        human.name = "Kevin";
        human.age = 13;
        human.eat();
        human.say("English");
        System.out.println(human.name); // Kevin
        Person human1 = new Person(); 
        System.out.println(human1.name); // null
    }

我們建立兩個實例,而兩個實例是在不同的堆空間中,因此不會相互影響。因此它們各自有獨立的屬性,如果宣告為 static 則為共用。

以下寫法讓 human2 和 human 指向同一個在堆的實例地址。這邊在說明屬性會加載至堆空間(非 static),局部變數則是棧空間

Person human2 = human;
System.out.println(human2.name); // Kevin
System.out.println(human2.age); // 13

匿名物件

簡單來說是沒有變數名稱的實例,每 new 一次就是一個不同地址的實例,此種方式通常會在多型時使用。

class Phone {
    private double price;

    public void playGame(){
        System.out.println("Play Game");
    }

    public void call(){
        System.out.println("Call~~");
    }
}

    public static void main(String[] args) {
        Phone p = new Phone();
        p.call();
        p.playGame();

        // 匿名
        new Phone().call();
        new Phone().playGame();
    }

方法

重載 (Overload)

在一個 class 中,可以有多個同樣名稱的方法,但其參數必須是不同。與回傳值或權限(private、public、protected)無關。從 Arrays 類別中即可看到可察看此鏈接

public void show(String list){

}

public void show(String list, String list2){

}

可變形參 (Varargs)

讓方法傳入的參數可以多個。限制有以下,假設當法有參數配合形參則形參必須為最後一個位置且在一個有形參的方法中只能存在一個形參。

public void show(String ... list){

}

注意以下的重載會造成錯誤,因為在沒有形參之前都以陣列方式實現,因此會認定是相通的

public void show(String ... s){

}

public void show(String[] s){
        
}

值傳遞機制

我們都知道方法必須由所在的類或物件調用才有意義。而方法參數會包含以下

在 JAVA 中都是以值傳遞實現,將實際參數的副本傳入方法內,而參數本身不受影響。如果為基本數據類型是將數據值傳遞給形參;如過為引用數據類型則是將地址值傳遞給形參。

基本數據類型

        int m = 10;
        int n = m;
        System.out.println("m: " + m +" n: "+ n); // m: 10 n: 10
        n = 50;
        System.out.println("m: " + m +" n: "+ n); // m: 10 n: 50

引用類型

class Order {
    int orderId;
}
    public static void main(String[] args) {
        Order o = new Order();
        o.orderId = 1001;
        Order o2 = o; // 指向堆中的同一地址
        System.out.println("o: " + o.orderId +" o2: "+ o2.orderId); // o: 1001 o2: 1001
        o2.orderId = 1000;
        System.out.println("o: " + o.orderId +" o2: "+ o2.orderId); // o: 1000 o2: 1000
    }

封裝與隱藏

簡單來說該隱藏的隱藏該暴露的暴露,封裝就在於實現該原理。在 JAVA 中有以下權限而封裝性由它們來實現

上述權限由小排到大,詳細可參考此鏈接

避免使用者直接引用屬性賦值時可使用,再搭配著 getter、setter 進行取值和賦值。這也實現了封裝性。除了限制前面描述內容外,還可以實現私有類的方法,使得該方法只能在該類中進行調用。

class Animal {
    private int age;

    public void setAge(int age){
        this.age = age;
    }

    public int getAge(){
        return this.age;
    }
}

上述所提到的屬性可修飾類(只限定於 default 和 public )、屬性、建構方法、內部類等。

建構方法

建構方法的作用

class Person {
    String name;
    int age;
}

// 調用,當中 Person() 就是建構方法
Person p = new Person();

屬性賦值先後順序

  1. 默認初始
  2. 顯示初始
  3. 建構方法賦值
  4. 透過物件賦值(方法或屬性)