多態:同一操做做用於不一樣的對象上面,能夠產生不一樣的解釋和不一樣的執行結果。
var makeSound = function (animal) {
if (animal instanceof Duck) {
console.log('嘎嘎嘎');
} else if (animal instanceof Chicken) {
console.log('咯咯咯');
}
};
var Duck = function () {};
var Chicken = function () {};
makeSound(new Duck()); // 嘎嘎嘎
makeSound(new Chicken()); // 咯咯咯
var makeSound = function (animal) {
animal.sound();
};
var Duck = function () {}
Duck.prototype.sound = function () {
console.log('嘎嘎嘎');
};
var Chicken = function () {}
Chicken.prototype.sound = function () {
console.log('咯咯咯');
};
makeSound(new Duck()); // 嘎嘎嘎
makeSound(new Chicken()); // 咯咯咯
- 類型檢查和多態:在靜態類型語言中編譯時會進行類型匹配檢查,不能給變量賦予不一樣類型的值因此須要向上轉型(當給一個類變量賦值時,這個變量的類型既可使用這個類自己,也可使用這個類的超類)。
- 使用繼承獲得多態效果
- 繼承一般包括實現繼承和接口繼承。
- 實現繼承例子:
先建立一個Animal 抽象類,再分別讓Duck 和Chicken 都繼承自Animal 抽象類
public abstract class Animal {
abstract void makeSound(); // 抽象方法
}
public class Chicken extends Animal {
public void makeSound() {
System.out.println("咯咯咯");
}
}
public class Duck extends Animal {
public void makeSound() {
System.out.println("嘎嘎嘎");
}
}
Animal duck = new Duck(); // (1)
Animal chicken = new Chicken(); // (2)
public class AnimalSound {
public void makeSound(Animal animal) { // 接受Animal 類型的參數
animal.makeSound();
}
}
public class Test {
public static void main(String args[]) {
AnimalSound animalSound = new AnimalSound();
Animal duck = new Duck();
Animal chicken = new Chicken();
animalSound.makeSound(duck); // 輸出嘎嘎嘎
animalSound.makeSound(chicken); // 輸出咯咯咯
}
}
- JavaScript的多態
- 多態的思想其實是把「作什麼」和「誰去作」分離開來。
- 在JavaScript 中,並不須要諸如向上轉型之類的技術來取得多態的效果。
- 多態在面向對象程序設計中的做用
- 《重構:改善既有代碼的設計》裏寫到:多態的最根本好處在於,你沒必要再向對象詢問「你是什麼類型」然後根據獲得的答案調用對象的某個行爲——你只管調用該行爲就是了,其餘的一切多態機制都會爲你安排穩當。
- 多態最根本的做用就是經過把過程化的條件分支語句轉化爲對象的多態性,從而消除這些條件分支語句。
- 地圖應用例子:
var googleMap = {
show: function () {
console.log('開始渲染谷歌地圖');
}
};
var baiduMap = {
show: function () {
console.log('開始渲染百度地圖');
}
};
var renderMap = function (map) {
if (map.show instanceof Function) {
map.show();
}
};
renderMap('google'); // 輸出:開始渲染谷歌地圖
renderMap('baidu'); // 輸出:開始渲染百度地圖
- 封裝:封裝的目的是將信息隱藏
- 封裝數據:JavaScript 並無提供對這些關鍵字的支持,咱們只能依賴變量的做用域來實現封裝特性,並且只能模擬出public 和private 這兩種封裝性。例子:
var myObject = (function () {
var __name = 'sven'; // 私有(private)變量
return {
getName: function () { // 公開(public)方法
return __name;
}
}
})();
console.log(myObject.getName()); // 輸出:sven
console.log(myObject.__name) // 輸出:undefined
- 封裝類型:封裝類型是經過抽象類和接口來進行的。把對象的真正類型隱藏在抽象類或者接口以後,JavaScript 中,並無對抽象類和接口的支持。
- 封裝變化:封裝在更重要的層面體現爲封裝變化,《設計模式》一書曾提到以下文字,「考慮你的設計中哪些地方可能變化,這種方式與關注會致使從新設計的緣由相反。它不是考慮何時會迫使你的設計改變,而是考慮你怎樣纔可以在不從新設計的狀況下進行改變。這裏的關鍵在於封裝發生變化的概念,這是許多設計模式的主題。」
- 原型模式和基於原型繼承的JavaScript對象系統:JavaScript 也一樣遵照這些原型編程的基本規則
- 全部的數據都是對象
- 基本類型包括undefined、number、boolean、string、function、object。
- JavaScript 中的根對象是Object.prototype 對象,Object.prototype 對象是一個空的對象。
- 要獲得一個對象,不是經過實例化類,而是找到一個對象做爲原型並克隆它。