ts核心基礎之介面(Interface)
作為一個純粹的前端攻城獅,有時候很難理解面向物件的思維,所以,有些功能你能夠用JS完成,但是轉換成TS就有點不知所措了。
面向物件設計和程式設計遵循的幾個原則:
SOLID原則:
- SRP(Single Responsibility Principle) 單一職責原則;
- OCP(Open Closed Principle) 開/閉原則;
- LSP(Liskov Substitution Principle) 里氏替換原則;
- ISP(Interface Segregation Principle) 介面分離原則;
- DIP(Dependency Inversion Principle) 依賴反轉原則。
介面初探
接下來,我們使用一個例子來說明介面的工作原理:
function printLabel(labelObj:{ label:string }){
console.log( labelObj.label );
}
let myObj={ size:10,label:"Size 10 Object" };
printLabel(myObj);
- 1
- 2
- 3
- 4
- 5
- 6
這是一個簡單的函式,在呼叫printLabel時,會檢查傳入引數的型別,並且只檢查那些必需屬性是否存在,並且型別是否匹配。下面利用介面重寫上面的例子
interface labelValue{
label:string;
}
function printLabel(labelObj:labelValue) {
console.log( labelObj.label );
}
let myObj2={ size:10,label:"Size 10 Object" };
printLabel(myObj2);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
在引數型別檢查的時候,會發現引數遵循的是介面labelValue的規範,然後就回去檢查是不是符合介面所描述的規範。
介面就相當於是一個約束,讓大家都遵循。
介面的擴充套件
//shape介面
interface Shape{
//顏色
color:string;
}
interface Triangle extends Shape{
//邊數
sideNum:number;
}
let triangle=<Triangle>{};
triangle.color="blue" ;
triangle.sideNum=3;
let square:Shape;
square.color="red";
//報錯
//square.sideNum=4;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
介面的擴充套件就是給多添加了一些約束。一個介面可以擴充套件多個介面,用“,”隔開,當一個介面擴充套件另一個介面,也繼承了該介面的約束。
從上面例子中可以看出,Triangle介面繼承了Shape介面。
而triangle變數遵循的是Triangle介面,所以也遵循Triangle介面繼承而來的約束。
而square變數遵循的是Shape介面,不能夠往下繼承,所以只遵循Shape介面的約束。而Shape接口裡面沒有定義sideNum的這個屬性,所以報錯。
類實現介面
interface ClockInterface{
currentTime:Date;
getTime(d:Date);
}
class Clock implements ClockInterface{
currentTime:Date;
getTime(){
console.log("123");
}
constructor(h:number,m:number){}
}
let clock1=new Clock(30,40);
clock1.getTime();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
類實現介面本質上也是一樣的,即類遵循介面的約束,接口裡面寫了多少個函式、引數,實現的類裡面也要寫相同的函式、引數。
介面繼承類
class Point{
x:number;
y:number;
constructor(){}
log(){
console.log('123456');
}
}
interface Point3d extends Point{
z:number;
}
var point3d:Point3d={
x:1,
y:2,
z:3,
log(){
//console.log('7777');
console.log();
}
}
//point3d.log();//7777
point3d.log(); //空的 並沒列印
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
官方解釋:當介面繼承了一個類型別時,它會繼承類的成員但不包括其實現。
也就是說,介面繼承類值繼承了它的約束條件,具體的值並不繼承。從上面例子中可以看出Point3d繼承了Point類,然後就繼承了Point類所遵循的約束條件。也就是說,Point介面實際上是這樣的:
interface Point{
x:number;
y:number;
log(){}
}
- 1
- 2
- 3
- 4
- 5
Point3d介面實際上是這樣的:
interface Point3d{
x:number;
y:number;
z:number;
log(){}
}
- 1
- 2
- 3
- 4
- 5
- 6
總結
介面擴充套件(繼承)介面
interfaceA extends interfaceB
- 1
類實現介面
classA implements interfaceA
- 1
介面繼承類
interfaceB extends classB
- 1
另外類擴充套件類
classA extends classB
- 1
有人肯分不清上面時候用extends,什麼時候用implements。
記住一句話,只要涉及到繼承就是extends.