作为一个纯粹的前端攻城狮,有时候很难理解面向对象的思维,所以,有些功能你能够用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) 依赖反转原则。

想了解具体详情的可以去程序员该有的艺术气质–SOLID原则看看

接口初探​ 

接下来,我们使用一个例子来说明接口的工作原理:

  1. ​function printLabel(labelObj:{ label:string }){​

  2. ​console.log( labelObj.label );​

  3. ​}​

  4. ​let myObj={ size:10,label:"Size 10 Object" };​

  5. ​printLabel(myObj);​

这是一个简单的函数,在调用printLabel时,会检查传入参数的类型,并且只检查那些必需属性是否存在,并且类型是否匹配。下面利用接口重写上面的例子

  1. ​interface labelValue{​

  2. ​label:string;​

  3. ​}​

  4. ​function printLabel(labelObj:labelValue){​

  5. ​console.log( labelObj.label );​

  6. ​}​

  7. ​let myObj2={ size:10,label:"Size 10 Object" };​

  8. ​printLabel(myObj2);​

在参数类型检查的时候,会发现参数遵循的是接口labelValue的规范,然后就回去检查是不是符合接口所描述的规范。 

接口就相当于是一个约束,让大家都遵循。

接口的扩展

  1. ​//shape接口​

  2. ​interface Shape{​

  3. ​//颜色​

  4. ​color:string;​

  5. ​}​

  6. ​interface Triangle extends Shape{​

  7. ​//边数​

  8. ​sideNum:number;​

  9. ​}​

  10. ​let triangle=<Triangle>{};​

  11. ​triangle.color="blue";​

  12. ​triangle.sideNum=3;​

  13. ​let square:Shape;​

  14. ​square.color="red";​

  15. ​//报错​

  16. ​//square.sideNum=4;​

接口的扩展就是给多添加了一些约束。一个接口可以扩展多个接口,用“,”隔开,当一个接口扩展另一个接口,也继承了该接口的约束。

从上面例子中可以看出,Triangle接口继承了Shape接口。 

而triangle变量遵循的是Triangle接口,所以也遵循Triangle接口继承而来的约束。 

而square变量遵循的是Shape接口,不能够往下继承,所以只遵循Shape接口的约束。而Shape接口里面没有定义sideNum的这个属性,所以报错。

类实现接口

  1. ​interface ClockInterface{​

  2. ​currentTime:Date;​

  3. ​getTime(d:Date);​

  4. ​}​

  5. ​class Clock implements ClockInterface{​

  6. ​currentTime:Date;​

  7. ​getTime(){​

  8. ​console.log("123");​

  9. ​}​

  10. ​constructor(h:number,m:number){}​

  11. ​}​

  12. ​let clock1=new Clock(30,40);​

  13. ​clock1.getTime();​

类实现接口本质上也是一样的,即类遵循接口的约束,接口里面写了多少个函数、参数,实现的类里面也要写相同的函数、参数。

接口继承类

  1. ​class Point{​

  2. ​x:number;​

  3. ​y:number;​

  4. ​constructor(){}​

  5. ​log(){​

  6. ​console.log('123456');​

  7. ​}​

  8. ​}​

  9. ​interface Point3d extends Point{​

  10. ​z:number;​

  11. ​}​

  12. ​var point3d:Point3d={​

  13. ​x:1,​

  14. ​y:2,​

  15. ​z:3,​

  16. ​log(){​

  17. ​//console.log('7777');​

  18. ​console.log();​

  19. ​}​

  20. ​}​

  21. ​//point3d.log();//7777​

  22. ​point3d.log(); //空的 并没打印​

官方解释:当接口继承了一个类类型时,它会继承类的成员但不包括其实现。 

也就是说,接口继承类值继承了它的约束条件,具体的值并不继承。从上面例子中可以看出Point3d继承了Point类,然后就继承了Point类所遵循的约束条件。也就是说,Point接口实际上是这样的:

  1. ​interface Point{​

  2. ​x:number;​

  3. ​y:number;​

  4. ​log(){}​

  5. ​}​

Point3d接口实际上是这样的:

  1. ​interface Point3d{​

  2. ​x:number;​

  3. ​y:number;​

  4. ​z:number;​

  5. ​log(){}​

  6. ​}​

总结

接口扩展(继承)接口

interfaceA extends interfaceB

类实现接口

classA implements interfaceA

接口继承类

interfaceB extends classB

另外类扩展类

classA extends classB

有人肯分不清上面时候用extends,什么时候用implements。 
记住一句话,只要涉及到继承就是extends.