Tina Tang's Blog

在哪裡跌倒了,就在哪裡躺下來

0%

Java筆記(1)-物件導向(OOP)

物件導向(Object-oriented programming)是程式開發的抽象方針,將物件作為程式的基本單元,將程式和資料封裝其中,以提高軟體的重用性、靈活性和擴充性。

類別(class)

類別(class)是建立物件(object)的藍圖,內部定義了具體的屬性(attribute)方法(method),一旦類別做了實體化(new)的動作之後,就可以產生物件(object),這個具體的物件就會擁有該類別所定義的屬性,並且可以執行該類別所定義的方法。

類別可能包括:

  • 屬性(attribute):變數(variable),需要記憶的資訊。
  • 方法(method):函式(function),能夠提供的服務。
  • 建構子/建構函式(constructor):設定初始化函式(function)
    • 建構子是「不可以」宣告回傳值型態,即使寫 void 也不行。
    • 建構子名稱需和該類別(class)同名。

建構子的多載(overload)

多載(overloading):

  • 函數名稱相同,引數個數不同
  • 引數個數相同,引數型態(type)不同

相似功能的函數,以相同的名稱來命名之;透過不同的引數個數,或是不同的型態,來執行相對應的功能。

範例程式碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class Dog {
/* 屬性 */
String type;
String color;
Integer age;
Integer weight;

/* 建構子 */
public Dog() { // 定義無引數的建構子
this.type = "米格魯";
}

public Dog(String type, String color, Integer age) { // 定義有引數的建構子
this.type = type;
this.color = color;
this.age = age;
}

public Dog(String type, Integer age, Integer weight) { // 定義有引數的建構子
this.type = type;
this.age = age;
this.weight = weight;
}
}

public class Main {
public static void main(String[] args) {
Dog dog1 = new Dog("黃金獵犬", "金毛", 7); // 建構子的多載
Dog dog2 = new Dog();
Dog dog3 = new Dog("薩摩耶", 5, 20);

System.out.println("type:" + dog1.type + " color:" + dog1.color + " age:" + dog1.age + " weight:" + dog1.weight);
System.out.println("type:" + dog2.type + " color:" + dog2.color + " age:" + dog2.age + " weight:" + dog2.weight);
System.out.println("type:" + dog3.type + " color:" + dog3.color + " age:" + dog3.age + " weight:" + dog3.weight);
}
}

執行結果:

1
2
3
type:黃金獵犬 color:金毛 age:7 weight:null
type:米格魯 color:null age:null weight:null
type:薩摩耶 color:null age:5 weight:20

物件(object)

物件是實體的,由定義好的類別去建立一個物件,並將它實例化,可以是一個變數或是一個函式。

物件可能包括:

  • 屬性(attribute):變數(variable),需要記憶的資訊。
  • 方法(method):函式(function),能夠提供的服務。

延續上面的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class Dog {
/* 屬性 */
String type;
String color;
Integer age;
Integer weight;

/* 建構子 */
public Dog() { // 定義無引數的建構子
this.type = "米格魯";
}

public Dog(String type, String color, Integer age) { // 定義有引數的建構子
this.type = type;
this.color = color;
this.age = age;
}

public Dog(String type, Integer age, Integer weight) { // 定義有引數的建構子
this.type = type;
this.age = age;
this.weight = weight;
}

/* 方法 */
public String getDogInfo() {
return "type:" + type + " color:" + color + " age:" + age + " weight:" + weight;
}
}

public class Main {
public static void main(String[] args) {
Dog dog1 = new Dog("黃金獵犬", "金毛", 7); // 建構子的多載
Dog dog2 = new Dog();
Dog dog3 = new Dog("薩摩耶", 5, 20);

System.out.println(dog1.getDogInfo());
System.out.println(dog2.getDogInfo());
System.out.println(dog3.getDogInfo());
}
}

執行結果:

1
2
3
type:黃金獵犬 color:金毛 age:7 weight:null
type:米格魯 color:null age:null weight:null
type:薩摩耶 color:null age:5 weight:20

有了 Dog 這個類別之後,可以產出很多 Dog 資料(dog1, dog2, dog3…),每個 Dog 都是物件,每一個物件是獨立的個體,彼此互不影響。


物件導向的三大特性

物件導向的三大特性包括:封裝(Encapsulation)繼承(Inheritance)多型(Polymorphism)

封裝(Encapsulation)

所謂封裝(Encapsulation),是指類別的設計者可以指定其他的類別能否存取自己的某個 member,也就是存取範圍的控制(對外的開放程度)

封裝包含了兩個重要的觀念:

  • 控制物件外部進行互動的出入口
  • 隱藏物件內部的細節資訊

Java 定義了四種存取範圍:

  • private:只有 自己才可以存取,使用關鍵字 private
  • package:只有和自己同一個 package 的 class 才可以存取,沒有相對應的關鍵字。
  • protected:只有同一個 package 或是 自己的子類別才可以存取,使用關鍵字 protected
  • public:所有的 class 都可以存取,使用關鍵字 public

如果 member 的前面沒有 private / protected / public 其中一個修飾字,則該 member 的存取範圍就是 package。從以上的敘述,讀者可以推知這四種存取範圍的大小是:
public > protected > package > private

繼承(Inheritance)

子類別(sub class)可以繼承父類別(super class)的屬性和方法,而不需重新定義,有程式碼再利用的概念。

  • 每個子類別只能有一個父類別,而父類別可擁有一個以上的子類別。
  • 兩者之間的關係可以用「is a」表示:SmartPhone(子類別) is a Product(父類別)
  • 透過關鍵字 extends 繼承來自父類別的 member。

多型(Polymorphism)

多型(Polymorphism)可以分為兩種類型:

  • 編譯時多型 - 多載(Overloading)。
  • 執行時多型 - 覆寫(Overriding)。
多載(Overloading)

有多個相同名稱的方法,但是傳入不同的參數就會執行不同的敘述。

範例:

1
2
3
public void setDogInfo(String type, String color, Integer age, Integer weight)
public void setDogInfo(String type, String color, Integer age)
public void setDogInfo(String type, Integer age, Integer weight)

再使用前面的 Dog class 舉例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
public class Dog {
/* 屬性 */
String type;
String color;
Integer age;
Integer weight;

/* 建構子 */
public Dog() { //定義無引數的建構子
this.type = "米格魯";
}

public Dog(String type, String color, Integer age) { // 定義有引數的建構子
this.type = type;
this.color = color;
this.age = age;
}

public Dog(String type, Integer age, Integer weight) { // 定義有引數的建構子
this.type = type;
this.age = age;
this.weight = weight;
}

/* 方法 */
public String getDogInfo() {
return "type:" + type + " color:" + color + " age:" + age + " weight:" + weight;
}

public void setDogInfo(String type, String color, Integer age, Integer weight) {
this.type = type;
this.color = color;
this.age = age;
this.weight = weight;
}

public void setDogInfo(String type, String color, Integer age) {
this.type = type;
this.color = color;
this.age = age;
}

public void setDogInfo(String type, Integer age, Integer weight) {
this.type = type;
this.age = age;
this.weight = weight;
}
}

public class Main {
public static void main(String[] args) {
// 將物件實例化
Dog dog1 = new Dog();
Dog dog2 = new Dog();
Dog dog3 = new Dog();

// 設定 Dog 資料
dog1.setDogInfo("黃金獵犬", "金毛", 7);
dog2.setDogInfo("薩摩耶", 5, 20);
dog3.setDogInfo("米格魯", "金毛", 3, 15);

// 印出 Dog 資料
System.out.println(dog1.getDogInfo());
System.out.println(dog2.getDogInfo());
System.out.println(dog3.getDogInfo());
}
}

執行結果:

1
2
3
type:黃金獵犬 color:金毛 age:7 weight:null
type:薩摩耶 color:null age:5 weight:20
type:米格魯 color:金毛 age:3 weight:15
覆寫(Overriding)

子類別可以覆寫父類別方法,使其擁有不同於父類別的行為。

父類別範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Animal {
/* 屬性 */
String type;

/* 建構子 */
public Animal() {
this.type = "貓";
}

/* 方法 */
public String getInfo() {
return "動物資料: type:" + type;
}

public void setType(String type) {
this.type = type;
}
}

子類別範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Dog extends Animal {
/* 屬性 */
String species;
String color;
Integer age;
Integer weight;

/* 方法 */
public String getInfo() { // 覆寫父類別方法
return "小狗資料: type:" + type + " species:" + species + " color:" + color + " age:" + age + " weight:" + weight;
}

public void setInfo(String species, String color, Integer age, Integer weight) {
this.species = species;
this.color = color;
this.age = age;
this.weight = weight;
}
}

Main 函式範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Main {
public static void main(String[] args) {
// 將物件實例化
Animal animal = new Animal();
Dog dog = new Dog();

// 設定資料
dog.setType("狗"); // 使用父類別的方法
dog.setInfo("米格魯", "金毛", 3, 15);

// 印出資料
System.out.println(animal.getInfo());
System.out.println(dog.getInfo());
}
}

執行結果:

1
2
動物資料: type:貓
小狗資料: type:狗 species:米格魯 color:金毛 age:3 weight:15

原本父類別的 getInfo() 方法只能取得 type。
因子類別覆寫了父類別的 getInfo() 方法,可取得 type、species、color、age 和 weight。

參考資料

物件導向(Object-oriented programming)
Java 學習系列