1. 程式人生 > >ts核心基礎之介面(Interface)

ts核心基礎之介面(Interface)

作為一個純粹的前端攻城獅,有時候很難理解面向物件的思維,所以,有些功能你能夠用JS完成,但是轉換成TS就有點不知所措了。

面向物件設計和程式設計遵循的幾個原則: 
SOLID原則:

  1. SRP(Single Responsibility Principle) 單一職責原則;
  2. OCP(Open Closed Principle) 開/閉原則;
  3. LSP(Liskov Substitution Principle) 里氏替換原則;
  4. ISP(Interface Segregation Principle) 介面分離原則;
  5. 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.