在使用優雅的建構子存取修飾符(Constructor Access Modifiers)之後,我們可能會發現:如果我用 private 的話不就不能存取那個 member variable 了嗎?或許有人又會說:『加個 get
和 set
就好了啊。』恩,我相信會這麼說的人之前應該有很高的機率是寫 Java 的。
那我們就先來看看,如果我們想要存取 member variable 最簡單的方式(就是不要增加 method啦)可以怎麼做:
class Rectangele {
constructor(private width?: number, private length?: number) { }
showWidthAndLength(): void {
console.log('width is ' + this.width, 'length is ' + this.length);
}
}
let rectangle1 = new Rectangele(10, 20);
rectangle1.showWidthAndLength();
以上面的程式碼來說,如果我們想要存取 width
或 length
, 單純使用 rectangle1.width
或 rectangle.length
肯定會出錯,因為 width
或 length
目前都是屬於 private 私有層級的。
那如果將 private 改成 public 呢?
constructor(private width?: number, private length?: number) { }
如果改成上述那樣,我們就可以用 rectangle1.width = 某個數字
(length 亦同) 這種方式直接來存取了。可是,又有另一個問題,假設我們想要限制 width
與 length
都必須要是大於零得正整數呢?
這時候就一定要增加 set
和 get
函式了。下面是增加函式後的結果:
class Rectangele {
constructor(private width?: number, private length?: number) { }
showWidthAndLength(): void {
console.log('width is ' + this.width, 'length is ' + this.length);
}
setWidth(width: number): void {
if (width <= 0) {
throw new Error("value cannot be less or equal to 0.")
}
this.width = width;
}
getWidth(): number {
return this.width;
}
setLength(length: number) {
if (length <= 0) {
throw new Error("value cannot be less or equal to 0.")
}
this.length = length;
}
getLength(): number {
return this.length;
}
}
這樣一來就可以達到我們在改變 width
或 length
的內容時,如果他小於或等於 0, 我們就可以丟出一個錯誤來達到防護的目的。不過,這樣做又產生了另一個問題,也就是我們在取直或給值的時候會變成下面這樣做:
let rect = new Rectangle(10, 20);
// 取得 width 的值
let width = rect.getWidth();
// 設定 width
rect.setLength(1111);
有發現嗎?有別於先前用 public 的做法,這次我們改用兩個不同的函式去取值以及設定值。那這樣程式寫起來不就又不優雅了,優雅只做了一半。因次,今天的主題就要登場了 -- Property (屬性)
我們只要使用屬性,就可以解決這個問題。他的語法就是使用 set VARIABLE_NAME 以及 get VARIABLE_NAME, 直接來看範例:
class Rectangele {
constructor(private _width?: number, private _length?: number) { }
showWidthAndLength(): void {
console.log('width is ' + this.width, 'length is ' + this.length);
}
set width(value: number) { // 請注意getter 或 setter 是不能寫回傳型別的,否則會出錯。
if (value <= 0) {
throw new Error("value cannot be 0 or less than 0.")
}
this.width = value;
}
get width() {
return this._width;
}
set length(value: number) {
if (value <= 0) {
throw new Error("value cannot be 0 or less than 0.")
}
this._length = value;
}
get length() {
return this._length;
}
}
這樣我們就可以用原本很優雅的方式來給值或取值了。就像下面這樣:
Rectangle rect = new Rectangle(1, 2);
rect.width = 101;
let width = rect.width;
最後,如果你有注意到的話,你會發現在建構子的部分,我把
constructor(private width?: number, private length?: number) { }
改成
constructor(private _width?: number, private _length?: number) { }
其實這個目的就是要 setter 和 getter 的名字不要和建構子裡面的變數名稱,也就是會變成 member variable 的名稱相衝突,所以我們就在建構子的參數前面都加了個底線。