本篇的主旨:
1 | class Post { |
extends
若是要建立另一個 Class,但同時包含上面的 Class 的內容,可以使用 extends 來做擴展1
2
3class News extends Post {}
let news = new News();
news.page(); // 第四篇了
也可以覆蓋原本定義的方法:1
2
3
4
5
6
7class News extends Post {
page(): void {
console.log('這是 news')
}
}
let news = new News();
news.page(); // 這是 news
Modifiers
- Public:任何類別以及繼承的子類別都可以調用。
- Private:只有當前類別內可以調用。
如以下範例,若是調用 .page() 的話,則會出現錯誤。1
2
3
4
5
6
7
8class Post {
private page(): void {
console.log('第四篇了')
}
}
let post = new Post();
post.page(); // Property 'page' is private and only accessible within class 'Post'
加上 private 因為只能在當前類別中調用,所以應該這樣使用:
用 displayPage 調用 page,外部再呼叫 displayPage 函式1
2
3
4
5
6
7
8
9
10
11class Post {
private page(): void {
console.log('第四篇了')
}
displayPage(): void {
this.page()
}
}
let post = new Post();
post.displayPage(); // 第四篇了
- protected:除了當前類別,繼承的子類別也可以調用
1
2
3
4
5
6
7
8
9
10
11
12class Post {
protected page(): void {
console.log('第四篇了')
}
}
class News extends Post {
disaplayPage(): void {
this.page()
}
}
let news = new News();
news.disaplayPage(); // 第四篇了
透過設定 Modifiers 可以確保某些函式無法隨意被調用,在 TS 中是會出現錯誤,但也要注意在編譯後是不會有限制的,所以仍是可以執行的。
constructor
使用 constructor 可以在 Class 中定義一個構造函式。1
2
3
4
5class Post {
constructor(public page: number) {}
}
let post = new Post(2);
console.log(post.page) // 2
super
1 | class Post { |
Classes & Interfaces
在前一篇 Interfaces 提到,它是用來定義值的型別,可以說是用來描述他的 Shape(形),而實際行為則需要透過 Classes 來制定。
如以下的舉例:
新聞 (News) 與部落格 (Blog) 都具有文章,而文章(Article)都需要包含了名稱以及第幾頁,因此我們用 interface 來定義 Article 需要包含的內容。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25interface Article {
name: string;
page: number;
}
class News implements Article {
name: string;
page: number;
constructor(name: string, page: number) {
this.name = name;
this.page = page
}
}
class Blog implements Article {
name: string;
page: number;
constructor(name: string, page: number) {
this.name = name;
this.page = page
}
}
let news = new News('新聞', 1);
let blog = new Blog('部落格', 4);
可以發現兩個 class 中的內容是重複的,因此也可以使用一個 Class 來做擴展,以下範例在 interface 還多增加一個 read,但 read 是的宣告是用在 News 這個 class 中的1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26interface Article {
name: string;
page: number;
read: boolean;
}
class Post {
name: string;
page: number;
constructor(name: string, page: number) {
this.name = name;
this.page = page
}
}
class News extends Post implements Article {
constructor(public read: boolean, name: string, page: number) {
super(name, page)
}
display() {
console.log(this.name + this.page + '必讀:' + this.read)
}
}
let news = new News(false, '新聞', 1);
news.display(); //
implements 也可以用兩個 interface,這邊把剛剛的 read 獨立出來,
只在 News 這個 class 去 implements。則在 News 就需要有 read,但 Blog 就可以不用。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38interface Article {
name: string;
page: number;
}
interface ArticleRead {
read: boolean;
}
class Post {
name: string;
page: number;
constructor(name: string, page: number) {
this.name = name;
this.page = page
}
}
class News extends Post implements Article, ArticleRead {
constructor(public read: boolean, name: string, page: number) {
super(name, page)
}
display() {
console.log(this.name + this.page + '必讀:' + this.read)
}
}
class Blog extends Post implements Article {
display() {
console.log(this.name + this.page)
}
}
let news = new News(false, '新聞', 1);
news.display();
let blog = new Blog('部落格', 4);
blog.display();
小補充
interface 也可以繼承 interface,這樣的話,news 必須與有 read1
2
3
4
5
6
7
8
9
10
11
12interface ArticleRead {
read: boolean;
}
interface Article extends ArticleRead {
name: string;
page: number;
}
let news: Article = {
name: '文章',
page: 5,
read: false,
}
透過 Class 可以建構可重複使用的組件,而加上 Interfaces 可以將共通的部分提取出來,讓共通處可以確保參數及其型別的定義都為一致。
參考資料:
Class - TypeScript
Udemy - Typescript: The Complete Developer’s Guide 2020
類別與介面 - TypeScript 新手指南