物件導向
物件導向程式,是一種具有物件概念的程式設計模式。
以下參考維基百科的敘述:
物件導向程式設計
物件導向程式設計(英語:Object-oriented programming,縮寫:OOP)是種具有物件概念的程式設計典範,同時也是一種程式開發的抽象方針。它可能包含資料、特性、程式碼與方法。物件則指的是類別(class)的實例。它將物件作為程式的基本單元,將程式和資料封裝其中,以提高軟體的重用性、靈活性和擴充性,物件裡的程式可以存取及經常修改物件相關連的資料。在物件導向程式程式設計裡,電腦程式會被設計成彼此相關的物件。
物件導向程式設計可以看作一種在程式中包含各種獨立而又互相呼叫的物件的思想,這與傳統的思想剛好相反:傳統的程式設計主張將程式看作一系列函式的集合,或者直接就是一系列對電腦下達的指令。物件導向程式設計中的每一個物件都應該能夠接受資料、處理資料並將資料傳達給其它物件,因此它們都可以被看作一個小型的「機器」,即物件。目前已經被證實的是,物件導向程式設計推廣了程式的靈活性和可維護性,並且在大型專案設計中廣為應用。此外,支持者聲稱物件導向程式設計要比以往的做法更加便於學習,因為它能夠讓人們更簡單地設計並維護程式,使得程式更加便於分析、設計、理解。反對者在某些領域對此予以否認。
當我們提到物件導向的時候,它不僅指一種程式設計方法。它更多意義上是一種程式開發方式。在這一方面,我們必須了解更多關於物件導向系統分析和物件導向設計(Object Oriented Design,簡稱OOD)方面的知識。許多流行的程式語言是物件導向的,它們的風格就是會透由物件來創出實例。
重要的物件導向程式語言包含Common Lisp、Python、C++、Objective-C、Smalltalk、Delphi、Java、Swift、C#、Perl、Ruby、JavaScript 與 PHP等。
另外,物件導向具備三大特性:
- 封裝
- 繼承
- 多型
封裝
封裝是將程式碼拆分成許多的「模組」,降低「模組」 和 「模組」 之間的關聯性。
除此之外,也可以降低複雜度讓開發和維護更容易。
封裝除了將程式碼拆分之外,還涉及到「能見度」的問題。
也就是模組內部實作的函式、變數,要不要暴露給別的模組、或是同一個模組的不同類別(可能是自己的子類別、內部類別)知道,這就是基於「能見度」所必須考慮到的設計問題。
繼承
繼承的目的,是讓你可以基於現有類別的基礎上,建立一個新的類別。以用來擴充、修改、或是重複使用原有類別中的功能。
被繼承的類別一般是稱為「父類別」,而繼承的類別一般稱為父類別的「子類別」。
這裡帶入一個情境來解釋,如下所示:
class Animal {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
class Dog extends Animal {}
class Cat extends Animal {}
class Bird extends Animal {}
class Rat extends Animal {}
上面的程式碼定義了一個父類別Animal,並加上屬性name,
子類別Dog、Cat、Bird、Rat各自繼承Animal。如此一來這四個子類別同時都有name的屬性可以使用。
多型
多型是指「相同的方法名稱」,可以有「不同的實作方式」。
以下是使用情境:
class Animal {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
void barking() {
System.out.println("叫聲");
}
}
class Dog extends Animal {
@Override
void barking() {
System.out.println("汪汪汪~~");
}
}
class Cat extends Animal {
@Override
void barking() {
System.out.println("喵喵喵~~");
}
}
class Bird extends Animal {
@Override
void barking() {
System.out.println("啾啾啾~~");
}
}
class Rat extends Animal {
@Override
void barking() {
System.out.println("嘰嘰嘰~~");
}
}
由於各種動物的叫聲不同。因此我在父類別Animal中,加入了barking()方法。
子類別則用override的方式,重寫barking()方法中的動作,用法如下:
public class MyClass {
public static void main(String args[]) {
Animal animal = new Animal();
animal.barking();
Dog dog = new Dog();
dog.barking();
Cat cat = new Cat();
cat.barking();
Bird bird = new Bird();
bird.barking();
Rat rat = new Rat();
rat.barking();
}
}
以下為輸出結果:
叫聲
汪汪汪~~
喵喵喵~~
啾啾啾~~
嘰嘰嘰~~
上面的情境中用到了override(重寫)方法,接下來則是另一種情境overload(多載)。
假設各個動物的叫聲會因為情緒而有所不同,我們可以針對這個情境使用多載來實現,如下:
public class MyClass {
public static void main(String args[]) {
Animal animal = new Animal();
animal.barking();
animal.barking(Animal.FEEL_HAPPY);
animal.barking(Animal.FEEL_ANGRY);
Dog dog = new Dog();
dog.barking();
dog.barking(Animal.FEEL_HAPPY);
dog.barking(Animal.FEEL_ANGRY);
}
}
class Animal {
public static final int FEEL_HAPPY = 0;
public static final int FEEL_ANGRY = 1;
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
void barking() {
System.out.println("叫聲");
}
void barking(int feeling) {
switch (feeling) {
case FEEL_HAPPY:
System.out.println("高興的叫聲");
break;
case FEEL_ANGRY:
System.out.println("生氣的叫聲");
break;
default:
break;
}
}
}
class Dog extends Animal {
@Override
void barking() {
System.out.println("汪汪汪~~");
}
@Override
void barking(int feeling) {
switch (feeling) {
case FEEL_HAPPY:
System.out.println("汪~~汪汪~~");
break;
case FEEL_ANGRY:
System.out.println("吼~~~汪~~!!!");
break;
default:
break;
}
}
}
執行結果如下:
叫聲
高興的叫聲
生氣的叫聲
汪汪汪~~
汪~~汪汪~~
吼~~~汪~~!!!