11# 介绍
22
3- 传统的JavaScript程序使用函数和基于原型的继承来创建可重用的组件,但这对于熟悉使用面向对象方式的程序员来说有些棘手,因为他们用的是基于类的继承并且对象是从类构建出来的 。
4- 从ECMAScript 2015,也就是ECMAScript 6,JavaScript程序将可以使用这种基于类的面向对象方法 。
5- 在TypeScript里 ,我们允许开发者现在就使用这些特性,并且编译后的JavaScript可以在所有主流浏览器和平台上运行,而不需要等到下个JavaScript版本。
3+ 传统的JavaScript程序使用函数和基于原型的继承来创建可重用的组件,但对于熟悉使用面向对象方式的程序员来讲就有些棘手,因为他们用的是基于类的继承并且对象是由类构建出来的 。
4+ 从ECMAScript 2015,也就是ECMAScript 6开始,JavaScript程序员将能够使用基于类的面向对象的方式 。
5+ 使用TypeScript ,我们允许开发者现在就使用这些特性,并且编译后的JavaScript可以在所有主流浏览器和平台上运行,而不需要等到下个JavaScript版本。
66
77# 类
88
@@ -28,13 +28,13 @@ let greeter = new Greeter("world");
2828你会注意到,我们在引用任何一个类成员的时候都用了` this ` 。
2929它表示我们访问的是类的成员。
3030
31- 最后一行,我们使用` new ` 构造了Greeter类的一个实例 。
31+ 最后一行,我们使用` new ` 构造了 ` Greeter ` 类的一个实例 。
3232它会调用之前定义的构造函数,创建一个` Greeter ` 类型的新对象,并执行构造函数初始化它。
3333
3434# 继承
3535
3636在TypeScript里,我们可以使用常用的面向对象模式。
37- 当然,基于类的程序设计中最基本的模式是允许使用继承来扩展一个类 。
37+ 当然,基于类的程序设计中最基本的模式是允许使用继承来扩展现有的类 。
3838
3939看下面的例子:
4040
@@ -70,14 +70,14 @@ sam.move();
7070tom .move (34 );
7171```
7272
73- 这个例子展示了TypeScript中继承的一些特征,与其它语言类似 。
74- 我们使用` extends ` 来创建子类 。你可以看到` Horse ` 和` Snake ` 类是基类` Animal ` 的子类,并且可以访问其属性和方法。
73+ 这个例子展示了TypeScript中继承的一些特征,它们与其它语言类似 。
74+ 我们使用` extends ` 关键字来创建子类 。你可以看到` Horse ` 和` Snake ` 类是基类` Animal ` 的子类,并且可以访问其属性和方法。
7575
76- 包含constructor函数的派生类必须调用 ` super() ` ,它会执行基类的构造方法。
76+ 包含构造函数的派生类必须调用 ` super() ` ,它会执行基类的构造方法。
7777
7878这个例子演示了如何在子类里可以重写父类的方法。
79- ` Snake ` 类和` Horse ` 类都创建了` move ` 方法,重写了从 ` Animal ` 继承来的` move ` 方法,使得` move ` 方法根据不同的类而具有不同的功能。
80- 注意,即使` tom ` 被声明为` Animal ` 类型,因为它的值是 ` Horse ` ,` tom.move(34) ` 调用 ` Horse ` 里的重写方法:
79+ ` Snake ` 类和` Horse ` 类都创建了` move ` 方法,它们重写了从 ` Animal ` 继承来的` move ` 方法,使得` move ` 方法根据不同的类而具有不同的功能。
80+ 注意,即使` tom ` 被声明为` Animal ` 类型,但因为它的值是 ` Horse ` ,` tom.move(34) ` 会调用 ` Horse ` 里的重写方法:
8181
8282``` text
8383Slithering...
@@ -88,11 +88,11 @@ Tommy the Palomino moved 34m.
8888
8989# 公共,私有与受保护的修饰符
9090
91- ## 默认为公有
91+ ## 默认为 ` public `
9292
9393在上面的例子里,我们可以自由的访问程序里定义的成员。
9494如果你对其它语言中的类比较了解,就会注意到我们在之前的代码里并没有使用` public ` 来做修饰;例如,C#要求必须明确地使用` public ` 指定成员是可见的。
95- 在TypeScript里,每个成员默认为 ` public ` 的 。
95+ 在TypeScript里,成员都默认为 ` public ` 。
9696
9797你也可以明确的将一个成员标记成` public ` 。
9898我们可以用下面的方式来重写上面的` Animal ` 类:
@@ -121,13 +121,13 @@ new Animal("Cat").name; // Error: 'name' is private;
121121```
122122
123123TypeScript使用的是结构性类型系统。
124- 当我们比较两种不同的类型时,并不在乎它们从哪儿来的 ,如果所有成员的类型都是兼容的,我们就认为它们的类型是兼容的。
124+ 当我们比较两种不同的类型时,并不在乎它们从何处而来 ,如果所有成员的类型都是兼容的,我们就认为它们的类型是兼容的。
125125
126126然而,当我们比较带有` private ` 或` protected ` 成员的类型的时候,情况就不同了。
127- 如果其中一个类型里包含一个` private ` 成员,那么只有当另外一个类型中也存在这样一个` private ` 成员, 并且它们是来自同一处声明时 ,我们才认为这两个类型是兼容的。
127+ 如果其中一个类型里包含一个` private ` 成员,那么只有当另外一个类型中也存在这样一个` private ` 成员, 并且它们都是来自同一处声明时 ,我们才认为这两个类型是兼容的。
128128对于` protected ` 成员也使用这个规则。
129129
130- 下面来看一个例子,详细的解释了这点 :
130+ 下面来看一个例子,更好地说明了这一点 :
131131
132132``` ts
133133class Animal {
@@ -187,7 +187,7 @@ console.log(howard.getElevatorPitch());
187187console .log (howard .name ); // error
188188```
189189
190- 注意,我们不能在` Person ` 类外使用` name ` ,但是我们仍然可以通过` Employee ` 类的实例方法访问,因为` Employee ` 是由` Person ` 派生出来的 。
190+ 注意,我们不能在` Person ` 类外使用` name ` ,但是我们仍然可以通过` Employee ` 类的实例方法访问,因为` Employee ` 是由` Person ` 派生而来的 。
191191
192192构造函数也可以被标记成` protected ` 。
193193这意味着这个类不能在包含它的类外被实例化,但是能被继承。比如,
@@ -216,7 +216,7 @@ let howard = new Employee("Howard", "Sales");
216216let john = new Person (" John" ); // Error: The 'Person' constructor is protected
217217```
218218
219- # readonly 修饰符
219+ # readonly修饰符
220220
221221你可以使用` readonly ` 关键字将属性设置为只读的。
222222只读属性必须在声明时或构造函数里被初始化。
@@ -256,11 +256,11 @@ class Animal {
256256
257257# 存取器
258258
259- TypeScript支持getters /setters来截取对对象成员的访问。
259+ TypeScript支持通过getters /setters来截取对对象成员的访问。
260260它能帮助你有效的控制对对象成员的访问。
261261
262- 下面来看如何把一类改写成使用 ` get ` 和` set ` 。
263- 首先是一个没用使用存取器的例子 。
262+ 下面来看如何把一个简单的类改写成使用 ` get ` 和` set ` 。
263+ 首先,我们从一个没有使用存取器的例子开始 。
264264
265265``` ts
266266class Employee {
@@ -276,7 +276,7 @@ if (employee.fullName) {
276276
277277我们可以随意的设置` fullName ` ,这是非常方便的,但是这也可能会带来麻烦。
278278
279- 下面这个版本里,我们先检查用户密码是否正确,然后再允许其修改employee 。
279+ 下面这个版本里,我们先检查用户密码是否正确,然后再允许其修改员工信息 。
280280我们把对` fullName ` 的直接访问改成了可以检查密码的` set ` 方法。
281281我们也加了一个` get ` 方法,让上面的例子仍然可以工作。
282282
@@ -307,16 +307,21 @@ if (employee.fullName) {
307307}
308308```
309309
310- 我们可以修改一下密码,来验证一下存取器是否是工作的。当密码不对时,会提示我们没有权限去修改employee 。
310+ 我们可以修改一下密码,来验证一下存取器是否是工作的。当密码不对时,会提示我们没有权限去修改员工 。
311311
312- 注意:若要使用存取器,要求设置编译器输出目标为ECMAScript 5或更高。
312+ 对于存取器有下面几点需要注意的:
313+
314+ 首先,存取器要求你将编译器设置为输出ECMAScript 5或更高。
315+ 不支持降级到ECMAScript 3。
316+ 其次,只带有` get ` 不带有` set ` 的存取器自动被推断为` readonly ` 。
317+ 这在从代码生成` .d.ts ` 文件时是有帮助的,因为利用这个属性的用户会看到不允许够改变它的值。
313318
314319# 静态属性
315320
316321到目前为止,我们只讨论了类的实例成员,那些仅当类被实例化的时候才会被初始化的属性。
317322我们也可以创建类的静态成员,这些属性存在于类本身上面而不是类的实例上。
318323在这个例子里,我们使用` static ` 定义` origin ` ,因为它是所有网格都会用到的属性。
319- 每个实例想要访问这个属性的时候,都要在origin前面加上类名 。
324+ 每个实例想要访问这个属性的时候,都要在 ` origin ` 前面加上类名 。
320325如同在实例属性上使用` this. ` 前缀来访问属性一样,这里我们使用` Grid. ` 来访问静态属性。
321326
322327``` ts
@@ -339,8 +344,8 @@ console.log(grid2.calculateDistanceFromOrigin({x: 10, y: 10}));
339344
340345# 抽象类
341346
342- 抽象类是供其它类继承的基类 。
343- 他们一般不会直接被实例化 。
347+ 抽象类做为其它派生类的基类使用 。
348+ 它们一般不会直接被实例化 。
344349不同于接口,抽象类可以包含成员的实现细节。
345350` abstract ` 关键字是用于定义抽象类和在抽象类内部定义抽象方法。
346351
@@ -355,8 +360,8 @@ abstract class Animal {
355360
356361抽象类中的抽象方法不包含具体实现并且必须在派生类中实现。
357362抽象方法的语法与接口方法相似。
358- 两者都是定义方法签名不包含方法体 。
359- 然而,抽象方法必须使用 ` abstract ` 关键字并且可以包含访问符 。
363+ 两者都是定义方法签名但不包含方法体 。
364+ 然而,抽象方法必须包含 ` abstract ` 关键字并且可以包含访问修饰符 。
360365
361366``` ts
362367abstract class Department {
@@ -398,8 +403,8 @@ department.generateReports(); // error: method doesn't exist on declared abstrac
398403
399404## 构造函数
400405
401- 当你在TypeScript里定义类的时候,实际上同时定义了很多东西 。
402- 首先是类的 * 实例* 的类型。
406+ 当你在TypeScript里声明了一个类的时候,实际上同时声明了很多东西 。
407+ 首先就是类的 * 实例* 的类型。
403408
404409``` ts
405410class Greeter {
@@ -417,7 +422,7 @@ greeter = new Greeter("world");
417422console .log (greeter .greet ());
418423```
419424
420- 在这里 ,我们写了` let greeter: Greeter ` ,意思是` Greeter ` 类实例的类型是 ` Greeter ` 。
425+ 这里 ,我们写了` let greeter: Greeter ` ,意思是` Greeter ` 类的实例的类型是 ` Greeter ` 。
421426这对于用过其它面向对象语言的程序员来讲已经是老习惯了。
422427
423428我们也创建了一个叫做* 构造函数* 的值。
@@ -441,11 +446,11 @@ console.log(greeter.greet());
441446```
442447
443448上面的代码里,` let Greeter ` 将被赋值为构造函数。
444- 当我们使用 ` new ` 并执行这个函数后 ,便会得到一个类的实例。
449+ 当我们调用 ` new ` 并执行了这个函数后 ,便会得到一个类的实例。
445450这个构造函数也包含了类的所有静态属性。
446- 换个角度说,我们可以认为类具有实例部分与静态部分这两个部分 。
451+ 换个角度说,我们可以认为类具有 * 实例部分 * 与 * 静态部分 * 这两个部分 。
447452
448- 让我们来改写一下这个例子 ,看看它们之前的区别:
453+ 让我们稍微改写一下这个例子 ,看看它们之前的区别:
449454
450455``` ts
451456class Greeter {
@@ -467,7 +472,8 @@ console.log(greeter1.greet());
467472
468473let greeterMaker: typeof Greeter = Greeter ;
469474greeterMaker .standardGreeting = " Hey there!" ;
470- let greeter2: Greeter = new greeterMaker ();
475+
476+ let greeter2: Greeter = new greeterMaker ();
471477console .log (greeter2 .greet ());
472478```
473479
@@ -485,8 +491,8 @@ console.log(greeter2.greet());
485491
486492## 把类当做接口使用
487493
488- 如上一节里所讲的,类定义会创建两个东西:类实例的类型和一个构造函数 。
489- 因为类可以创建出类型,所以你能够在可以使用接口的地方使用类 。
494+ 如上一节里所讲的,类定义会创建两个东西:类的实例类型和一个构造函数 。
495+ 因为类可以创建出类型,所以你能够在允许使用接口的地方使用类 。
490496
491497``` ts
492498class Point {
0 commit comments