10.1 多型的基礎
多型是物件導向程式設計(OOP)中的一個關鍵概念。從廣義來說,多型允許不同類別的物件使用同一個介面來處理資料。 在JavaScript的上下文中,這意味著不同的物件可以具有相同名稱的方法,而這些方法可以在不知道其具體類型的情況下調用在物件上。
多型的類型
在JavaScript中,主要的多型類型有:
1. Ad-hoc 多型 (ad-hoc polymorphism):
- 方法的多型,對不同類型的物件調用具有相同名稱的方法
- 例如函數和運算子的重載(這在JavaScript中不被直接支持,但可以被模擬)
2. 子類型多型 (Subtype polymorphism):
- 子類型或包含多型,當不同類別的物件繼承自同一個基類時,可以被當作基類物件來處理
- 這是透過繼承和介面來實現的主要多型類型
多型的優點:
- 簡化代碼: 多型允許撰寫更靈活和通用的代碼,可以處理不同類別的物件,無需知道其具體類型。
- 擴展性: 多型使得可以在不改變現有代碼的情況下向系統添加新類型和行為。
- 支持性: 多型促進了職責的更好區分,提升代碼的可讀性和支持性。
10.2 JavaScript中的多型示例
透過繼承實現的子類型多型
示例 1: 使用一個介面處理不同類型的物件
在這個例子中,函數playWithAnimal
接受一個Animal
類型的物件並調用方法makeSound
。
Dog
和Cat
物件繼承自Animal
,且覆蓋makeSound
方法,並在每個物件調用該方法時,產生不同的結果。
class Animal {
makeSound() {
console.log('Some generic sound');
}
}
class Dog extends Animal {
makeSound() {
console.log('Woof!');
}
}
class Cat extends Animal {
makeSound() {
console.log('Meow!');
}
}
function playWithAnimal(animal) {
animal.makeSound();
}
const dog = new Dog();
const cat = new Cat();
playWithAnimal(dog); // 會顯示: Woof!
playWithAnimal(cat); // 會顯示: Meow!
10.3 通過介面實現多型 (Duck Typing)
在JavaScript中沒有像TypeScript或Java那樣的內建介面支持。取而代之的是使用一種叫做「鴨子類型」(Duck Typing)的方法。 這意味著,只要物件具備所需的方法和屬性,就被認為符合介面要求,而不管其具體類型或繼承。
鴨子法則 (duck): 如果某物看起來像鴨子,又游得像鴨子,還叫得像鴨子,那它很可能就是鴨子。
示例 2: 使用鴨子類型
在這個例子中,函數takeOff
接受任何具有fly
方法的物件。Bird
和Airplane
物件實現了fly
方法,因此可以傳遞給takeOff
。
class Bird {
fly() {
console.log('Flying...');
}
}
class Airplane {
fly() {
console.log('Jet engine roaring...');
}
}
function takeOff(flyingObject) {
flyingObject.fly();
}
const bird = new Bird();
const airplane = new Airplane();
takeOff(bird); // 會顯示: Flying...
takeOff(airplane); // 會顯示: Jet engine roaring...
10.4 通過函數實現多型
在JavaScript中,函數是頭等對象,可以傳遞和用於實現多型行為。
示例 3: 通過函數實現多型
在這個例子中,函數greet
接受另一個函數作為參數並調用它。這允許使用不同的函數來執行不同的操作。
function greetMorning() {
console.log('Good morning!');
}
function greetEvening() {
console.log('Good evening!');
}
function greet(greetingFunction) {
greetingFunction();
}
greet(greetMorning); // 會顯示: Good morning!
greet(greetEvening); // 會顯示: Good evening!
10.5 通過方法重載實現多型 (模擬)
JavaScript不支持直接的方法重載,如同其他一些程式語言。然而,可以通過函數參數和類型檢查來模擬方法重載。
示例 4: 模擬方法重載
在這個例子中,方法add
接受兩個參數並根據其類型執行不同的操作。如果參數是數字,則方法做加法。如果參數是數組,則方法合併它們。
class Calculator {
add(a, b) {
if (typeof a === 'number' && typeof b === 'number') {
return a + b;
} else if (Array.isArray(a) && Array.isArray(b)) {
return a.concat(b);
} else {
throw new Error('Invalid arguments');
}
}
}
const calc = new Calculator();
console.log(calc.add(1, 2)); // 會顯示: 3
console.log(calc.add([1, 2], [3, 4])); // 會顯示: [1, 2, 3, 4]
GO TO FULL VERSION