iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 5
2
Software Development

為什麼世界需要Typescript系列 第 5

物件導向的封裝繼承 - 05

封裝(Encapsulation)

封裝就是將物件(Class) 內部的資料隱藏起來, 只能透過物件(Class) 本身自己存取內部的欄位(field), 屬性(propery) 或者方法(function) , 這些內部的細節資料或者方法(function)內的邏輯隱藏起來, 其他物件不需要也無法瞭解此物件的內部細節, 也不能存取這些資料.

換句話說, 對這個物件(Class) 外面使用者只需要理解它的公開方法就好, 不需要了解裡面內部的構造.

在JavaScript 中想要封裝Person 的name 屬性,

function Person() {
   this._name = "flash";
}

但是在Javascript 世界裡沒有分私有或公開成員的設計, 目前比較簡單常見的作法, 就是在私有成員(或方法)的名稱前面, 加上下底線符號 "_", 用來表示這是私有的(private)成員, 這只是由程式開發者自行規定撰寫上的區分差別, 與語言本身特性無關.

對Javascript 語言來說, 成員名稱前有沒有底線符號 _, 都是視為一樣的變數, 至於要如何保護這些私有成員, 就靠程式設計者自己了.

所以在Javascript 一旦你這樣使用

var a = new Person();
console.log(a._name);

在VSCode 編輯器編輯這段程式碼的時候, 不會彈出警告訊息, 執行時期也不會噴例外存取錯誤.

在Typescript 世界裡卻很簡單, 只需要在成員名稱前面加上 private 關鍵字

class Person {
   private name: string = "flash";
   public getName(): string {
      return this.name;
   }
}

如此一來, 當我們試圖在Typescript 裡面

var a = new Person();
console.log(a.name);

VSCode 編輯器馬上就會告訴你這段程式碼有問題, 而且也不會讓你編譯成功, 達到保護物件(Class)內部目的.

多型 (Polymorphism)

多型就是相同名稱的方法(function), 傳入不同的參數, 會執行不同的動作.

Javascript 不支援成員方法參數的多型, 只能override

function Person() {
   this.show = function() {
      console.log("阿..");
   }
}

function Cat() {
   this.prototype = Person;
   this.prototype();
   this.show = function() {
      console.log("喵..");
   }
}

function show(animal) {
   animal.show();
}

var a = new Person();
var b = new Cat();
show(a);
show(b);

在這裡Cat 繼承Person 的方法是用

this.prototype = Person;
this.prototype();

但如果子類別(Class) 還想執行父類別(Class)中被 override 的方法時, 則可以修改一下prototype 繼承的做法

var Person = function() {
   this.show = function() {
      console.log("阿.."); 
   }
}

Person.prototype = Person;

var Cat = function() {
  Person.call(this);
  this.show = function() {
    this.superClass.show.call(this);
    console.log('喵...');
  };
};

Cat.prototype = new Person();
Cat.prototype.superClass = new Person();

function show(animal) {
   animal.show();
}

var a = new Person();
var b = new Cat();
show(a);
show(b);

你看你看, 是不是超麻煩的? 在Typescript 世界裡不用這麼麻煩, 只需在Cat Class 用相同一個方法名稱, 它就會自動override

class Person {
   show(): void {
      console.log("阿...");
   }
}

class Cat extends Person {
   show(): void {
      console.log("喵...");
   }
}

然後假設你也希望Cat 子類別要呼叫Person 父類別的show 方法, 也只需要這樣寫

class Cat extends Person {
   show(): void {
      super.show();     
   }
}

一個字 super 就可以搞定呼叫父類別這件事.

多載(Overloading)

多載就是有多個相同名稱的方法(function), 但是每一個參數的型態和數量不同, 這些方法就構成了方法的多載.

這裡有一個方法多載的例子, (注意這不是Javascript 也不是Typescript), 下面是C# 語言程式碼片段

public void show(string name) {
   console.log("Hello " + name);
}
public void show(string name, int amount) {
   console.log("Hello " + name + " money=" + amount);
}

Javascript 世界裡不支援多載(Overloading), 但是你可以用下面方式來模擬上述的多載例子

function show(name, amount) {
   if( amount == undefined ) {
      console.log("Hello " + name);
      return; 
   }
   console.log("Hello " + name + " money=" + amount);
}

你可以發現Javascript 是利用參數檢查是不是沒傳送的方式, 來模擬達到多載.


上一篇
物件導向的繼承 - 04
下一篇
多載方法 - 06
系列文
為什麼世界需要Typescript30

尚未有邦友留言

立即登入留言