>[danger] ##### 語言類型分類
[編譯型語言、解釋型語言、靜態類型語言、動態類型語言概念與區別](https://www.cnblogs.com/zy1987/p/3784753.html?utm_source=tuicool)
[Python是解釋型的強類型動態語言](https://zhuanlan.zhihu.com/p/113408690)
>[success] # 鴨子類型 -- 動態類型語言
* **起源**:意大利軟件工程師、Python軟件基金會研究員`Alex Martelli` 于2000年`python`的郵件組中最早將這個概念引入了程序設計范疇中
* **概念來源**:`Duck typing` 這個概念來源于美國印第安納州的詩人**詹姆斯·惠特科姆·萊利(James Whitcomb Riley,1849-1916)** 的詩句:` When I see a bird that walks like a duck and swims like a duck and quacks
like a duck, I call that bird a duck.`**中文意思** `當看到一只鳥走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那么這只鳥就可以被稱為鴨子`
* **鴨子類型是動態類型語言才具備的**(運行時才進行數據類型檢查 即在變量賦值時,才確定變量的數據類型,不用事先給變量指定數據類型 ),例如 `js` `python`
* **鴨子類型** `只關心對象的行為,不關心對象本身`
>[info] ## 鴨子案例
`《 javasprict 設計模式與開發實踐 》`書中有個例子,`js` 王國的國王覺得鴨子叫聲很美妙,他要組織一個大型的鴨子合唱團,一共需要`1000`只鴨子,但是最后全國只找到了`999`只,但還差一只,怎么辦?就在這個時候發現一只雞叫起來和鴨子一樣,這只雞就成了第`1000`個合唱團的成員
*****
根據鴨子類型去解釋上面的例子,**鴨子和雞就是編程時候的實例對象**
,我們**不關心**你是鴨子對象還是雞對象,**只關心**你能不能像鴨子一樣叫,這個叫就是`行為`
>[danger] ##### 案例
1. 像下面的代碼案例,以后不管你是雞鴨魚還是其他動物,只要你會鴨子叫就能加入合唱團,我們只需要吧這類實例放到`joinChoir`方法中
~~~
// 鴨子
const duck = {
duckSing:function () {
console.log('嘎嘎嘎')
}
}
// 會鴨子叫的雞
const chicken = {
duckSing:function () {
console.log('嘎嘎嘎')
}
}
const choir = [] // 合唱團
function joinChoir(animal) {
// 只關心你的行為 是能發出鴨子叫
if(animal && typeof animal.duckSing === 'function'){
choir.push(animal)
}
}
joinChoir(duck)
joinChoir(chicken)
console.log(choir) // 鴨子
~~~
>[success] # 多態 -- 靜態類型語言
* **多態解釋**:從多態的英文`prolymorphism`,也就是`poly(復數) + morph(形態)`,字面意思復數形態,概念上說**多態主要指** 同一種事物表現出來的多種形態,當**同一操作作用于不同的對象,可以有不同的解釋,產生不同的執行結果**
* **多態常見靜態類型語言**,例如接口的多種不同的實現方式即為多態,繼承重寫重載都體現了多態
* **多態的實際意義**在于屏蔽不同子類的差異性實現通用的編程帶來不同的效果
>[info] ## 多態的案例
`java `王國的國王覺得鴨子叫聲很美妙,他要組織一個大型的鴨子合唱團,一共需要1000只鴨子,但是最后全國只找到了999只,但還差一只,怎么辦?就在這個時候發現一只雞叫起來和鴨子一樣,這只雞就成了第1000個合唱團的成員
>[danger] ##### 案例
* 創建父類`Animal `
~~~
public class Animal {
public void sing() {
System.out.print('唱');
}
}
~~~
* 創建`Chicken`
~~~
class Chicken extends Animal {
public void sing() {
System.out.print('唱');
}
}
~~~
* 創建 `Duck`
~~~
class Duck extends Animal {
public void sing() {
System.out.print('唱');
}
}
~~~
* **沒有用多態**,但由于類型檢查`AnimalSound`類中的`makeSound`只接受`Duck`類型的導致當我們用`Chicken`的實例當成參數的時候報錯
~~~
public class AnimalSound {
public void makeSound( Duck duck ){ // (1)
duck.sing();
}
}
public class Test {
public static void main( String args[] ){
AnimalSound animalSound = new AnimalSound();
Duck duck = new Duck();
animalSound.makeSound( duck ); // 輸出:嘎嘎嘎
}
}
~~~
* **使用多態**,有一個特點就是可以向上轉型
~~~
public class AnimalSound {
public void makeSound( Animal animal ){
animal.sing();
}
}
~~~
>[info] ## 多態和鴨子區別
**多態**指的一類事物有多種形態,比如動物有多種形態:貓、狗、豬,像這里'貓、狗、豬'往上看都是動物,**鴨子**類型只要你像你就是我們需要的因此汽車叫的像鴨子,他也是鴨子他和鴨子沒有任何關聯只是單純像
>[info] ## 有了多態和鴨子類型
用書中的話來說,**將過程化的條件分支語句轉換為對象的多態性,從而消除這些條件語句**,像上面的案例我們從if判斷是那個類,在決定發出什么聲音,到后來真正的多態,我們不關心你是誰怎么叫,只要你能叫,發出指令你執行就可以
>[danger] ##### js 案例
書中給的場景:需要編寫地圖應用一開始選擇谷歌地圖,后來因為需求部分需要百度地圖,就可以利用多態的形式
~~~
const googleMap = {
show: function () {
console.log('開始渲染谷歌地圖');
}
};
const baiduMap = {
show: function () {
console.log('開始渲染百度地圖');
}
};
const renderMap = function (map) {
if (map.show instanceof Function) {
map.show();
}
};
renderMap(googleMap); // 輸出:開始渲染谷歌地圖
renderMap(baiduMap); // 輸出:開始渲染百度地圖
// 錯誤使用多態(過多的if判斷)
const renderMap = function (type) {
if (type=== 'google') {
googleMap.show()
}else if(type === 'baidu'){
baidu.show()
}
}
~~~
>[danger] ##### java 案例
* 父類
~~~
public abstract class Map {
public abstract void show();
}
~~~
* 子類
~~~
class BaiDuMap extends Map {
public void show() {
System.out.print('唱');
}
}
~~~
* 子類
~~~
class GoogleMap extends Map {
public void show() {
System.out.print('唱');
}
}
~~~
* 使用
~~~
public class App {
public void useMap(Map map) {
map.show();
}
// 否則要做兩個方法 判斷具體用那個對象
public void useBMap(BaiDuMap bM) {
new BaiDuMap().show();
}
// 否則要做兩個方法 判斷具體用那個對象
public void useGMap(BaiDuMap bM) {
new GoogleMap().show();
}
public static void main(String[] args) throws Exception {
BaiDuMap b = new BaiDuMap();
GoogleMap g = new GoogleMap();
App app = new App();
app.useMap(g);
app.useMap(b);
// 根據 實例判斷
// Map m = b;
// if (m instanceof BaiDuMap) {
// // .....
// } else {
// // .....
// }
}
}
~~~