本文講述了類的繼承、介面的實現中需要注意的一些小細節,同時也對類、介面的多繼承做了一些講解。
先看一下繼承
類的繼承
子類繼承了父類之後,就會將父類中定義的非 private 屬性以及方法都繼承下來
class Animal {
public name: string = "Animal";
public age: number;
sayHello() {
console.log(`Hello ${ this.name }`);
}
}
class Dog extends Animal {
age: number;
constructor(age) {
super();
this.age = age;
}
}
const dog = new Dog(6);
dog.sayHello();
複製程式碼
由於 Dog 繼承了 Animal 類,所以同時也繼承了 Animal 的 name 屬性和 sayHello 方法,因此可以直接使用 dog 例項呼叫 sayHello 方法。 那麼問題來了:如果可以進行多繼承,若多個父類中都包含同一個屬性,那麼子類使用的應該是哪個父類的屬性呢? 因此 TypeScript 中不允許進行多繼承,可是我就是想進行類的多繼承該怎麼辦呢?可以使用用下節所說的 Mixins 的方式。
類的多繼承(Mixins 模擬)
- 先定義兩個類,Person 和 Student 類
// Person 類
class Person {
name: string;
sayHello() {
console.log('tag', `Helo ${ this.name }!`)
}
}
// Student 類
class Student {
grade: number;
study() {
console.log('tag', ' I need Study!')
}
}
複製程式碼
- 下面建立一個類,結合 Person 和 Student 這兩個類 首先應該注意到的是,沒使用 extends 而是使用 implements。 把類當成了介面,僅使用 Person 和 Student 的型別而非其實現。 我們可以這麼做來達到目的,為將要mixin進來的屬性方法建立出佔位屬性。 這告訴編譯器這些成員在執行時是可用的。
class SmartObject implements Person, Student {
// Person
name: string = 'person';
sayHello: () => void;
// Activatable
grade: number = 3;
study: () => void;
}
複製程式碼
- 最後,把mixins混入定義的類,完成全部實現部分
// 把mixins混入定義的類
applyMixins(SmartObject, [Person, Student]);
// applyMixins 方法
function applyMixins(derivedCtor: any, baseCtors: any[]) {
baseCtors.forEach(baseCtor => {
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
derivedCtor.prototype[name] = baseCtor.prototype[name];
})
});
}
複製程式碼
介面與類之間的繼承
介面繼承類的方式以及特點與上面類的繼承和類的多繼承一致。
介面與介面之間的多繼承
介面與介面之間是可以直接進行多繼承的。
- 先定義兩個介面
// 阿里介面
interface Ali {
pay: () => void
}
// 騰訊介面
interface Tencent {
game: string
play: () => void
}
複製程式碼
- 在定義一個介面繼承 Ali、Tencent 介面
// 自己的介面
interface Self extends Ali, Tencent {
name: string
say: () => void
}
複製程式碼
此時Self 介面就包含了 Ali 和 Tencent 介面中所有的屬性和方法
- 驗證一下 用一個類實現 Self 介面,必須要將 Ali、 Tencent、 Self 介面中包含的所有屬性和方法都宣告瞭才可以,不然會編譯報錯
// 使用 Test 類實現 Self 介面
class Test implements Self {
game: string;
name: string;
pay() {
console.log('經常用於支付');
}
play() {
console.log('可以玩各種遊戲');
}
say() {
console.log('不知道說點兒什麼');
}
}
複製程式碼
再來看一下介面的實現
介面的實現
介面在定義的時候,不能初始化屬性以及方法,屬性不能進行初始化,方法不能實現方法體。 類實現介面之後,必須宣告介面中定義的屬性以及方法。
interface Animal {
name: string;
eat: () => void;
}
class Dog implements Animal {
name: string;
eat() {
console.log('tag', 'I love eat bone!')
}
}
const dog: Dog = new Dog();
dog.eat();
複製程式碼
類對於介面的多實現
一個類可以實現多個介面,不過要將實現的所有介面的屬性和方法都實現了。
// 動物介面
interface Animal {
name: string;
eat: () => void;
}
// 貓科介面
interface Felidae {
claw: number;
run: () => void;
}
// 讓貓類實現 Animal 和 Felidae 兩個介面
class Cat implements Animal, Felidae {
name: string;
claw: number;
eat() {
console.log('tag', 'I love eat Food!');
}
run: () {
console.log('tag', 'My speed is very fast!')
}
}
const dog: Dog = new Dog();
dog.eat();
複製程式碼
總結
-
類與類之間只能進行單繼承,想要實現多繼承需要使用 Mixins 的方式
-
介面繼承類也只能進行單繼承,想要實現多繼承需要使用 Mixins 的方式 Mixins 方式模擬多繼承的缺陷:
-
只能在繼承一級父類的方法和屬性
-
如果父類中含有同一種方法或屬性,會根據賦值的順序,先賦值的會被覆蓋掉
-
-
介面與介面之間可以直接進行多繼承
-
類實現介面可以進行多實現,每個介面用 , 隔開即可