物件導向的概念是一種寫程式碼的風格,是現在比較主流的一種方式,讓程式碼看起來比較有架構簡潔,至於整體的概念網路上有超級多,就不在多寫,主要著重在TypeScript的語法紀錄
內容目錄
如何寫class
首先先練習寫class幾個特點
- 習慣第一個字大寫
- 可以有屬性 > 變數
- 可以有方法 > 函式
- 可以使用new建立出來
- 屬性跟方法被建立後可以被 “.” 出來用跟修改
- constructor是建立之前跑的地方
建立一個簡單的class動物,在實現在貓跟狗上面,所以狗貓就有了name跟age的屬性,還有call跟action這兩個方法,嘗試改變狗的名子最後將兩邊印出來看
class Animal {
name: string;
age: number;
call() {}
action() {}
}
let dog = new Animal();
let cat = new Animal();
dog.name = "dog";
console.log(dog);
console.log(cat);
可以發現,狗有被賦予名子上去,而貓的名還沒被賦予值

再以剛剛為例,如果想要再new出來之前就有名子,那可以使用constructor來在建立的時候設定參數跟屬性,constructor是在物件被建立之前就會跑的地方
class Animal {
constructor(name: string) {
this.name = name;
}
name: string;
age: number;
call() {}
action() {}
}
let dog = new Animal("BigDog");
let cat = new Animal("cat");
console.log(dog);
console.log(cat);
class加入interface
前面有提到interface加入物件的方法,現在同樣的方式可以用來約束class的設定,那有幾個特點是
- 屬性一樣是設定型態
- 則方法是設定回傳值,參數不管
從範例可以知道,我們一樣要跟interface設定的一樣,把屬性建立好,但方法只要遵照他的回傳值,就可以了,參數不用特別設定一樣,也不會報錯,我們使用interface來約束自己,會盡量都遵照interface上面的設定
interface Animal {
name: string;
age: number;
call: (data: any) => string;
action: (data: number) => string;
sayHi: (data: string) => void;
}
class dog implements Animal {
name: string;
age: number;
call(data: any) {
return "";
}
action() {
return "";
}
sayHi() {}
run() {}
help() {}
}
如果沒有設定interface的屬性及方法,則會報錯提醒

class類別的繼承
這是class的一大特點,可以先設定一個初始大家都共用的class給大家繼承,讓有共同功能的class可以不用一直重複寫一樣的功能
所以根據範例的執行,我們貓跟狗又額外的繼承了Animal的class,這樣好處就是,我想要run這個方法,就不用在額外寫在兩個class上也能使用
class Animal {
run() {
console.log("run...");
}
}
class Dog extends Animal {}
class Cat extends Animal {}
const d1 = new Dog();
const c1 = new Cat();
d1.run();
c1.run();

覆蓋功能
如果你想要把原本的方法給覆蓋掉也是可以,只要在自己的class裡面寫一樣的方法,就可以達成覆蓋效果
class Animal {
run() {
console.log("run...");
}
}
class Dog extends Animal {
run() {
console.log("Dog...run...");
}
}
class Cat extends Animal {}
const d1 = new Dog();
const c1 = new Cat();
d1.run();
c1.run();

super調用父層的功能
因為方法已經被複寫,想要調用父層的方法就要使用super,那就可以把父層的東西又叫出來用
class Animal {
run() {
console.log("father...run...");
}
}
class Dog extends Animal {
run() {
super.run();
console.log("Dog...run...");
}
}
class Cat extends Animal {}
const d1 = new Dog();
d1.run();

父層的constructor
如果父層有constructor來建構初始內容,那麼建立(new)繼承的class(BigFish),就要依照constructor的參數給予設定並建立
範例中需要name這個參數,所以BigFish繼承了他,就要建構這個初始內容
class Fish {
name: string;
constructor(name: string) {
this.name = name;
}
swim() {
console.log("go..." + this.name);
}
}
class BigFish extends Fish {
swim() {
console.log("fish...go..." + this.name);
}
}
let bigFish = new BigFish("nimo");
bigFish.swim();

抽象類別
這是一個跟interface很像的功能,差別在於,interface不能原本就帶有一些功能,但抽象類別可以
- 抽象類別不能被建構(new)出來,只能被繼承
- 抽象類別跟interface的差別在於可以附帶一些功能
- 使用抽象方法跟屬性,強迫繼承對象實作這些方法跟屬性
範例來看
abstract class Animal {
abstract name: string;
run() {
console.log("abstract function run...");
}
abstract call(): void;
abstract hello(): string;
}
class Dog extends Animal {
name: string;
call() {}
hello() {
return "hi";
}
}
let dog = new Dog();
dog.run();

class的成員類型
這個概念有點像是使用權限,總共分為private、public、protected,分別是私有的、公開的、受保護的,直接做一張表來表示他們的使用範圍
public | protected | private | |
自己class內 | 可使用 | 可使用 | 可使用 |
繼承者 | 可使用 | 可使用 | 不可使用 |
建構(new) | 可使用 | 不可使用 | 不可使用 |
直接來測試當被建構出來之後,能使用多少屬性,結論是只有public可以使用
class Animal {
private name: string;
public age: number;
protected action: string;
}
let dog =new Animal()

那如果被繼承的話,可以使用多少權限,只有protected跟public可以使用

呼叫private的方法
如果真的需要使用到private的內容,可使用function把他呼叫出來,這樣可以繼續保有私有狀態不被任意改變,還可以取用裡面的值
class Animal {
private name: string = "tony";
public age: number;
protected action: string;
get() {
console.log(this.name);
}
}
let dog = new Animal();
dog.get();

class的靜態用法
可以把他當作一個全域的用法,不用透過建構(new)的方式,就可以取用class裡面的方法跟屬性,適合共用及需要全域,但又想要整理起來的一種用法
那從範例中的加油站,油的存量不可以隨意更改,但是透過remaining可以取來看,而refuel可以加油來使用加油站內的庫存油
至於為什麼不new出來改,是因為,new出來之後,存量就不再是共用的,而是自己的,所以要共用的東西要用static
class GasStation {
private static stock: number = 1000;
static refuel(oil: number) {
this.stock -= oil;
}
static remaining() {
console.log(this.stock);
}
}
function car1(oil: number) {
GasStation.refuel(oil);
GasStation.remaining();
}
car1(400);
car1(300);

總結
今天也是繼續學習布魯斯的 TypeScript 入門攻略|輕鬆打造實時聊天室這堂課,說到物件導向這個概念,其實我都一直想把他學好,但不是中途有事情,或是學過概念以後都沒用到,但這次重新學習TypeScript就是要把物件導向的觀念深植在我之後的程式碼當中,雖然我在JavaScript一直都有用物件在整理程式碼,但實際能做到事情還是跟class有很大程度的落差
透過課程的學習,我在這章節清楚的class以前完全搞不清楚的地方,全部都搞懂了,課程中清楚的比對每個方法的作用,讓我一直以來覺得沒必要的功能,現在都知道他原本的用途了,雖然有寫文章做筆記,但這只是讓我快速回憶的筆記,對於真正想學習的人,還是會建議聽過布魯斯的解講,比自己花時間理解還快上許多
