TypeScript 介面繼承

楚楚99發表於2022-07-07

1、TypeScript 介面繼承

和類一樣,介面也可以通過關鍵字 extents 相互繼承。介面繼承,分為:單繼承和多繼承,即繼承多個介面。另外,介面也可以繼承類,它會繼承類的成員,但不包括具體的實現,只會把類的成員作為一種宣告。本文主要總結一下TypeScript 介面繼承,方便大家進行系統化的學習。

2、單繼承

interface Shape {
   name: string;
}

interface Circle extends Shape {
   radius: number;
}

let circle = {} as Circle;
 
// 繼承了 Shape 的屬性
circle.name = "circle";

circle.radius = 10;

 

3、多繼承

介面能夠像類一樣對介面進行繼承,但不同的是類只能是單繼承,而介面既可以實現單繼承也可以多繼承,多個介面以逗號分隔。

 

interface Color {
   color: string;
}

interface Shape {
   name: string;
}

interface Circle extends Color, Shape {
   radius: number;
}

 

當一個介面繼承了其他介面後,子介面既包含了自身定義的型別成員,也包含了父介面中的型別成員。下例中,Circle介面同時繼承了Style介面和Shape介面,因此Circle介面中包含了color、name和radius屬性:

 

const c: Circle = {
   color: 'red',
   name: 'circle',
   radius: 10
};

 

4、介面繼承中的同名成員的相容問題

在介面繼承中,可能會出現同名成員,面對同名成員這種情況,怎麼處理呢?主要分為以下兩種情況:

4.1、同名成員的型別必須相容

如果子介面與父介面之間存在同名的型別成員,那麼子介面中的型別成員具有更高的優先順序。同時,子介面與父介面中的同名型別成員必須是型別相容的。也就是說,子介面中同名型別成員的型別需要能夠賦值給父介面中同名型別成員的型別,否則將產生編譯錯誤。示例如下:

interface Style {
   color: string;
}

interface Shape {
   name: string;
}

interface Circle extends Style, Shape {
   name: 'circle';
   color: number;
//  ~~~~~~~~~~~~~
//  編譯錯誤:'color' 型別不相容,
//  'number' 型別不能賦值給 'string' 型別
}

Circle介面同時繼承了Style介面和Shape介面。Circle介面與父介面之間存在同名的屬性name和color。Circle介面中name屬性的型別為字串字面量型別'circle',它能夠賦值給Shape介面中string型別的name屬性,因此是正確的。而Circle介面中color屬性的型別為number,它不能夠賦值給Color介面中string型別的color屬性,因此產生編譯錯誤。

4.2、同名成員的型別必須相同

如果僅是多個父介面之間存在同名的型別成員,而子介面本身沒有該同名型別成員,那麼父介面中同名型別成員的型別必須是完全相同的,否則將產生編譯錯誤。示例如下:

interface Color {
   draw(): { color: string };
}

interface Shape {
   draw(): { x: number; y: number };
}

interface Circle extends Style, Shape {}
//        ~~~~~~
//        編譯錯誤

 

Circle介面同時繼承了Color介面和Shape介面。Color介面和Shape介面都包含一個名為draw的方法,但兩者的返回值型別不同。當Circle介面嘗試將兩個draw方法合併時發生衝突,因此產生了編譯錯誤。

解決這個問題的一個辦法是,在Circle介面中定義一個同名的draw方法。這樣Circle介面中的draw方法會擁有更高的優先順序,從而取代父介面中的draw方法。這時編譯器將不再進行型別合併操作,因此也就不會發生合併衝突。但是要注意,Circle介面中定義的draw方法一定要與所有父介面中的draw方法是型別相容的。示例如下:

interface Color {
   draw(): { color: string };
}

interface Shape {
   draw(): { x: number; y: number };
}

interface Circle extends Color, Shape {
   draw(): { color: string; x: number; y: number };
}

Circle介面中定義了一個draw方法,它的返回值型別為“{ color: string; x: number; y: number }”。它既能賦值給“{ color: string }”型別,也能賦值給“{ x: number; y: number }”型別,因此不會產生編譯錯誤。

5、介面繼承類

介面可以對類實現繼承,但只能繼承類的成員,不會繼承類成員的實現。

class Person{
       name:string = 'Tom'
       age: number = 20
       sayHello():void{
              console.log('Hello world');
       }
}

interface IPerson extends Person{

}

 

class Peter extends Person implements IPerson{}

上述程式碼不會報錯,因為Peter類繼承了Person類,已經具有了Person中的成員,再去實現IPerson介面,即使不寫內容也不會報錯

class Gary implements IPerson{}

上述程式碼會報錯,直接實現介面就會報錯,因為介面繼承了Person類,所以介面中的屬性也應該在類Yannis中定義並實現

6、參考

http://www.mybatis.cn/typescript/1981.html

相關文章