1212
1313``` ts 
1414interface  Alarm  {
15-     alert();
15+     alert():   void ;
1616}
1717
1818class  Door  {
@@ -35,12 +35,12 @@ class Car implements Alarm {
3535
3636``` ts 
3737interface  Alarm  {
38-     alert();
38+     alert():   void ;
3939}
4040
4141interface  Light  {
42-     lightOn();
43-     lightOff();
42+     lightOn():   void ;
43+     lightOff():   void ;
4444}
4545
4646class  Car  implements  Alarm , Light  {
@@ -64,25 +64,29 @@ class Car implements Alarm, Light {
6464
6565``` ts 
6666interface  Alarm  {
67-     alert();
67+     alert():   void ;
6868}
6969
7070interface  LightableAlarm  extends  Alarm  {
71-     lightOn();
72-     lightOff();
71+     lightOn():   void ;
72+     lightOff():   void ;
7373}
7474``` 
7575
76- 上例中,我们使用  ` extends `  使  ` LightableAlarm `  继承  ` Alarm ` 。
76+ 这很好理解, ` LightableAlarm `  继承了  ` Alarm ` ,除了拥有  ` alert `  方法之外,还拥有两个新方法  ` lightOn `  和  ` lightOff ` 。
7777
7878## 接口继承类  
7979
80- 接口也可以继承类 :
80+ 常见的面向对象语言中,接口是不能继承类的,但是在 TypeScript 中却是可以的 :
8181
8282``` ts 
8383class  Point  {
8484    x:  number ;
8585    y:  number ;
86+     constructor (x :  number , y :  number ) {
87+         this .x  =  x ;
88+         this .y  =  y ;
89+     }
8690}
8791
8892interface  Point3d  extends  Point  {
@@ -92,43 +96,144 @@ interface Point3d extends Point {
9296let  point3d:  Point3d  =  {x: 1 , y: 2 , z: 3 };
9397``` 
9498
95- ## 混合类型  
99+ 为什么 TypeScript 能够支持接口继承类呢?
100+ 
101+ 实际上,当我们在声明 ` class Point `  时,除了会创建一个名为 ` Point `  的类之外,同时也创建了一个名为 ` Point `  的类型(实例的类型)。
102+ 
103+ 所以我们既可以将 ` Point `  当做一个类来用(使用 ` new `  创建它的实例):
104+ 
105+ ``` ts 
106+ class  Point  {
107+     x:  number ;
108+     y:  number ;
109+     constructor (x :  number , y :  number ) {
110+         this .x  =  x ;
111+         this .y  =  y ;
112+     }
113+ }
114+ 
115+ const   p =  new  Point (1 , 2 );
116+ ``` 
117+ 
118+ 也可以将 ` Point `  当做一个类型来用(使用 ` : Point `  表示参数的类型):
119+ 
120+ ``` ts 
121+ class  Point  {
122+     x:  number ;
123+     y:  number ;
124+     constructor (x :  number , y :  number ) {
125+         this .x  =  x ;
126+         this .y  =  y ;
127+     }
128+ }
129+ 
130+ function  printPoint(p :  Point ) {
131+     console .log (p .x , p .y );
132+ }
133+ 
134+ const   p =  new  Point (1 , 2 );
135+ 
136+ printPoint (p );
137+ ``` 
138+ 
139+ 这个例子实际上可以等价于:
140+ 
141+ ``` ts 
142+ class  Point  {
143+     x:  number ;
144+     y:  number ;
145+     constructor (x :  number , y :  number ) {
146+         this .x  =  x ;
147+         this .y  =  y ;
148+     }
149+ }
150+ 
151+ interface  PointInstanceType  {
152+     x:  number ;
153+     y:  number ;
154+ }
155+ 
156+ function  printPoint(p :  PointInstanceType ) {
157+     console .log (p .x , p .y );
158+ }
159+ 
160+ const   p =  new  Point (1 , 2 );
161+ 
162+ printPoint (p );
163+ ``` 
164+ 
165+ 上例中我们新声明的 ` PointInstanceType `  类型,与声明 ` class Point `  时创建的 ` Point `  类型是等价的。
96166
97- [ 之前学习过 ] ( ../basics/type-of-function.md#接口中函数的定义 ) ,可以使用接口的方式来定义一个函数需要符合的形状 :
167+ 所以回到  ` Point3d `  的例子中,我们就能很容易的理解为什么 TypeScript 能够支持接口继承类了 :
98168
99169``` ts 
100- interface  SearchFunc  {
101-     (source :  string , subString :  string ):  boolean ;
170+ class  Point  {
171+     x:  number ;
172+     y:  number ;
173+     constructor (x :  number , y :  number ) {
174+         this .x  =  x ;
175+         this .y  =  y ;
176+     }
177+ }
178+ 
179+ interface  PointInstanceType  {
180+     x:  number ;
181+     y:  number ;
102182}
103183
104- let  mySearch :   SearchFunc ; 
105- mySearch   =   function ( source :   string ,  subString :   string )  {
106-     return   source . search ( subString )  !==   - 1 ;
184+ //  等价于 interface Point3d extends PointInstanceType 
185+ interface   Point3d   extends   Point  {
186+     z :   number ;
107187}
188+ 
189+ let  point3d:  Point3d  =  {x: 1 , y: 2 , z: 3 };
108190``` 
109191
110- 有时候,一个函数还可以有自己的属性和方法:
192+ 当我们声明 ` interface Point3d extends Point `  时,` Point3d `  继承的实际上是类 ` Point `  的实例的类型。
193+ 
194+ 换句话说,我们实际上是定义了一个接口 ` Point3d `  继承另一个接口 ` PointInstanceType ` 。
195+ 
196+ 所以这种用法和接口继承接口没有什么本质的区别。
197+ 
198+ 值得注意的是,` PointInstanceType `  相比于 ` Point ` ,缺少了 ` constructor `  方法,这是因为声明 ` Point `  类时创建的 ` Point `  类型是不包含构造函数的。另外,除了构造函数是不包含的,静态属性/方法也是不包含的(实例的类型当然不应该包括构造函数和静态属性/方法):
111199
112200``` ts 
113- interface  Counter  {
114-     (start :  number ):  string ;
115-     interval:  number ;
116-     reset():  void ;
201+ class  Point  {
202+     /**  静态属性,坐标系原点 */ 
203+     static  origin =  new  Point (0 , 0 );
204+     /**  静态方法,计算与原点距离 */ 
205+     static  distanceToOrigin(p :  Point ) {
206+         return  
207+     }
208+     /**  实例属性,x 轴的值 */ 
209+     x:  number ;
210+     /**  实例属性,y 轴的值 */ 
211+     y:  number ;
212+     /**  构造函数 */ 
213+     constructor (x :  number , y :  number ) {
214+         this .x  =  x ;
215+         this .y  =  y ;
216+     }
217+     /**  实例方法,打印此点 */ 
218+     printPoint() {
219+         console .log (this .x , this .y );
220+     }
117221}
118222
119- function  getCounter():  Counter  {
120-     let  counter =  <Counter >function  (start :  number ) { };
121-     counter .interval  =  123 ;
122-     counter .reset  =  function  () { };
123-     return  counter ;
223+ interface  PointInstanceType  {
224+     x:  number ;
225+     y:  number ;
226+     printPoint():  void ;
124227}
125228
126- let  c =  getCounter ();
127- c (10 );
128- c .reset ();
129- c .interval  =  5.0 ;
229+ let  p1:  Point ;
230+ let  p2:  PointInstanceType ;
130231``` 
131232
233+ 上例中最后的类型 ` Point `  和类型 ` PointInstanceType `  是等价的。
234+ 
235+ 所以在接口继承类的时候,也只会继承它的实例属性/方法。
236+ 
132237## 参考  
133238
134239-  [ Interfaces] ( http://www.typescriptlang.org/docs/handbook/interfaces.html ) ([ 中文版] ( https://zhongsp.gitbooks.io/typescript-handbook/content/doc/handbook/Interfaces.html ) )
0 commit comments