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