typeScript中的面向物件程式設計學習心得
阿新 • • 發佈:2018-12-08
SOLID原則(設計模式的6大原則)
- 單一職責原則(SRP):表明軟體元件(函式、類、模組)必須專注與單一的任務(只有單一的職責)
- 開/閉原則(OCP):對擴充套件開放, 對修改關閉
- 里氏替換原則(LSP):物件應該可以是在不改變程式正確性的前提下被它的子類所替換.
- 介面隔離原則(ISP):應該將非常大的介面拆分成一些小的更具體的介面,多個特定特定客戶端介面要好於一個寬泛用途的介面
- 依賴反轉原則(DIP):依賴於一個抽象而不是一個例項
類
由屬性和方法組成, 屬性通常用來描述物件的特徵, 方法通常用來描述物件的行為。
其中有一個特殊的方法, 叫做構造方法(與java的構造方法一樣, 但是重寫構造方法有點麻煩),在通過new關鍵字建立一個類的例項的時候會被呼叫。
下面是一個簡單的例子, 定義了兩個類, 一個Person類和一個Email類
Person類: 三個屬性, 兩個方法
import {Email} from './email'; export class Person { public name : string; public surname : string; public email : Email; constructor(name, surname, email) { this.name = name; this.surname = surname; this.email = email; } greet() { alert('Hi'); } }
下面是Email類
export class Email { private email : string; constructor(email) { if (this.validateEamil(email)) { this.email = email; } else { throw new Error("invalid email!"); } } private validateEamil(email) { let re = /\[email protected]\S+\.\S+/; return re.test(email); } }
兩個類在檔案中的位置關係
這樣子寫是為了符合單一職責原則, 如果這樣寫不符合單一職責原則
export class Person {
public name : string;
public surname : string;
public email : Email;
constructor(name, surname, email) {
this.name = name;
this.surname = surname;
if (this.validateEamil(email)) {
this.email = email;
} else {
throw new Error("invalid email!");
}
}
validateEamil(email) {
let re = /\[email protected]\S+\.\S+/;
return re.test(email);
}
greet() {
alert('Hi');
}
}
因為validateEamil方法是和Person類的行為並無關聯
繼承
可以擴充套件已有的類,這個功能被稱為繼承,允許我們建立一個類(子類), 從已有的類(父類)上繼承所有的屬性和方法,子類還可以包含父類中沒有的屬性和方法。但是值得注意的是,一個子類只能繼承一個父類,不能繼承多個父類,沒有多重繼承。
可以看下面的一個例子, 還是用上面提到的Person類和Email類
Person類:
import {Email} from './email';
export class Person {
public name : string;
public surname : string;
public email : Email;
constructor(name: string, surname: string, email: Email) {
this.name = name;
this.surname = surname;
this.email = email;
}
greet() {
console.log('Hi');
}
}
Email類:
export class Email {
private email : string;
constructor(email) {
if (this.validateEamil(email)) {
this.email = email;
} else {
throw new Error("invalid email!");
}
}
private validateEamil(email) {
let re = /\[email protected]\S+\.\S+/;
return re.test(email);
}
}
現在用Teacher類繼承Person類, Teacher類可以有父類沒有的屬性和方法, 也可以重寫父類已經有的方法
Teacher類:
import {Person} from './person';
import {Email} from './email';
export class Teacher extends Person{
public subject: string[];
constructor(name: string, surname: string, email: Email, subject: string[]) {
super(name, surname, email);
this.subject = subject;
}
greet() {
super.greet();
console.log('我教 ' + this.subject);
}
teach() {
console.log('我是老師, 我教學生');
}
}
也可以有一個類繼承Teacher類, 那麼這個類會繼承Teacher類中的所有方法和屬性, 也會繼承Person中的所有屬性和方法
import {Teacher} from './teacher';
import {Email} from './email';
export class SchoolPrincipal extends Teacher{
constructor(name: string, surname: string, email: Email, subject: string[]) {
super(name, surname, email, subject);
}
}
//執行下面程式碼
let schoolPrincipal = new SchoolPrincipal("name", "surname", email, ["name1", "name2"]);
schoolPrincipal.greet();
schoolPrincipal.teach();
但是這裡Person和Teacher都有greet()方法,當呼叫greet方法時,呼叫的是Teacher的greet方法,可以得出結論:
- 父類(和父類的父類)有相同的方法的時候,呼叫直接繼承父類的方法