在 EcmaScript 6 中,我们将会拥有原生的类,而不是像现在通过原型链来实现。使用 TypeScript 我们能提前体验这一特性。
首先来看看一个简单的例子:
class Greeter { greeting: string; constructor(message: string) { this.greeting = message; } greet() { return "Hello, " + this.greeting; }}var greeter = new Greeter("world");
我们使用 class 关键字来定义了,使用 constructor 来定义构造函数,使用 this 关键字来指代当前对象。
除了构造函数关键字外,语法跟 C# 和 java 是比较像的。
作为面向对象三大基本特征之一,TypeScript 当然支持继承。
class Animal { name:string; constructor(theName: string) { this.name = theName; } move(meters: number = 0) { alert(this.name + " moved " + meters + "m."); }}class Snake extends Animal { constructor(name: string) { super(name); } move(meters = 5) { alert("Slithering..."); super.move(meters); }}class Horse extends Animal { constructor(name: string) { super(name); } move(meters = 45) { alert("Galloping..."); super.move(meters); }}var sam = new Snake("Sammy the Python");var tom: Animal = new Horse("Tommy the Palomino");sam.move();tom.move(34);
跟接口的继承一样,都是使用 extends 关键字来继承。在子类中,我们使用 super 关键字来访问父类。在上面代码中我们看到方法的参数中有等于号,这表示方法参数的默认值。如果我们调用该方法时,不写该参数或者传入 undefined,那么这个参数就会被赋予默认值。
sam.move();sam.move(undefined);
即上面这两段代码是等价的。
注意:TypeScript 跟 C# 和 java 一样,是不支持多继承的(虽然可以通过原型链实现)。
在 TypeScript 中,现在仅有两种访问修饰符,分别是 public 和 PRivate。
在之前的代码中,我们都能够正常访问到类中定义的属性。那么可见,类的属性默认的访问修饰符是 public 的。
class Animal { private name:string; constructor(theName: string) { this.name = theName; }}class Rhino extends Animal { constructor() { super("Rhino"); }}class Employee { private name:string; constructor(theName: string) { this.name = theName; } }var animal = new Animal("Goat");var rhino = new Rhino();var employee = new Employee("Bob");animal = rhino;animal = employee; //error: Animal and Employee are not compatible
我们将之前的代码中的属性的访问修饰符修改为 private 之后,就会发现编译无法通过了。
访问修饰符不仅仅可以作用于属性,还能作用于构造函数参数。这个是 TypeScript 中的一个语法糖。
class Animal { constructor(private name: string) { } move(meters: number) { alert(this.name + " moved " + meters + "m."); }}
那么构造函数中的 name 参数将会生成一个 private 的属性。
访问器
有时候我们在设置属性的时候,希望对输入进行检查,这时候就需要用到访问器了。
var passcode = "secret passcode";class Employee { private _fullName: string; get fullName(): string { return this._fullName; } set fullName(newName: string) { if (passcode && passcode == "secret passcode") { this._fullName = newName; } else { alert("Error: Unauthorized update of employee!"); } }}var employee = new Employee();employee.fullName = "Bob Smith";if (employee.fullName) { alert(employee.fullName);}
上面我们就为 fullName 属性定义了 get 和 set 访问器了。
在前面,我们定义的都是实例属性。那么如何定义静态属性呢?使用 static 关键字就可以了。
class Grid { static origin = {x: 0, y: 0}; calculateDistanceFromOrigin(point: {x: number; y: number;}) { var xDist = (point.x - Grid.origin.x); var yDist = (point.y - Grid.origin.y); return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale; } constructor (public scale: number) { }}var grid1 = new Grid(1.0); // 1x scalevar grid2 = new Grid(5.0); // 5x scalealert(grid1.calculateDistanceFromOrigin({x: 10, y: 10}));alert(grid2.calculateDistanceFromOrigin({x: 10, y: 10}));
注意的是,要访问静态属性,必须加上该静态属性所在的类作为前缀。
另外,静态属性也能配合访问修饰符使用。
class Test { private static _age: number; static get age(): number { return Test._age; } static set age(value: number) { Test._age = value; }}
新闻热点
疑难解答