传统的JavaScript注重用函数和基于原型的继承来创建可复用的组件,但这可能让用习惯面对对象方式的程序员感到棘手,因为他们的继承和创建对象都是由类而来的。从JavaScript的下一个版本,ECMAScript 6开始,JavaScript程序员就能够用基于这种基于类的面对对象方式来创建编写自己的程序了。在TypeScript中,不需要再等JavaScript的下一个版本就已经支持开发者使用这一技术了。 类 class Greeter { greeting: string; constructor(message: string) { this.greeting = message; } greet() { return "Hello, " + this.greeting; } } var greeter = new Greeter("world"); 如果你之前有使用过C#或者Java,会觉得语法非常相似。我们声明一个新的类"Greeter"。这个类里面有三个成员,一个名为"greeting"的属性,一个constructor和一个"greet"方法。 继承 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); 这个例子包含了TypeScript中继承的特性,当然,在其他语言中也一样。在这里,我们使用"extends"关键字来创建一个子类。你可以看到,这里"Horse"和"Snake"两个子类都基于"Animal"这个父类,并且对其特性进行了扩展。在这里,我们使用"extends"关键字来创建一个子类。你可以看到,这里"Horse"和"Snake"两个子类都基于"Animal"这个基类并且获取其特性。 公有和私有的修饰符 class Animal { private name:string; constructor(theName: string) { this.name = theName; } move(meters: number) { alert(this.name + " moved " + meters + "m."); } } 理解Private(私有) 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; // 错误: Animal 和 Employee 不兼容 在这个例子中,我们有一个"Animal"和一个"Rhino","Rhino"是"Animal"的一个子类。我们还有一个新的类"Employee",它看上去跟"Animal"类是完全相同的。我们给这些类分别创建实例,并且对他们进行相互赋值,看下将会发生什么。因为"animal"和"rhino"的私有成员都是从"Animal"类定义的"private name: string"共享而来的,所以他们是兼容的。然而,"employee"的情况却不是这样的。当我们试图将"employee"赋值给"animal",我们得到了一个错误,他们的类型是不兼容的。尽管"Employee"也有一个名称是"name"的私有成员,但它和在"Animal"中的私有成员"name"还是不相同的。 参数属性 class Animal { constructor(private name: string) { } move(meters: number) { alert(this.name + " moved " + meters + "m."); } } var goat = new Animal("Goat"); goat.move(25); // Goat moved 25 m. 通过这种方式使用"private"来创建和初始化私有成员,"public"也一样。 访问器 class Employee { fullName: string; } var employee = new Employee(); employee.fullName = "Bob Smith"; if (employee.fullName) { alert(employee.fullName); } 以上代码允许我们随意设置fullName,可能我们会觉得这样比较直接和方便,但这么随心所欲的改变名字也可能会导致问题。 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); } 为了证明现在访问需要密码,我们可以修改密码,然后我们会发现,当密码不符合的时候会弹出提示"Error: Unauthorized update of employee!"(错误:没有修改employee的权限)。 注意:访问器需要我们将文件以ECMAScript5编程输出。 tsc --target ES5 your.ts 静态属性 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 规模 var grid2 = new Grid(5.0); // 5x 规模 alert(grid1.calculateDistanceFromOrigin({x: 10, y: 10})); alert(grid2.calculateDistanceFromOrigin({x: 10, y: 10})); 高级技巧 class Greeter { greeting: string; constructor(message: string) { this.greeting = message; } greet() { return "Hello, " + this.greeting; } } var greeter: Greeter; greeter = new Greeter("world"); alert(greeter.greet()); 这里,当我们写"var greeter: Greeter",我们就已经将"Greeter"类的实例类型定义为"Greeter"了。这对于用过其它面向对象语言的程序员而言已经习以为常了。 var Greeter = (function () { function Greeter(message) { this.greeting = message; } Greeter.prototype.greet = function () { return "Hello, " + this.greeting; }; return Greeter; })(); var greeter; greeter = new Greeter("world"); alert(greeter.greet()); 在这里,"var Greeter"是指定构造函数。当我们使用"new"并且执行这个函数之后,便会得到一个类的实例。这个构造函数包含了类的所有的静态成员。换种说法,即类有静态部分和实例部分。 class Greeter { static standardGreeting = "Hello, there"; greeting: string; greet() { if (this.greeting) { return "Hello, " + this.greeting; } else { return Greeter.standardGreeting; } } } var greeter1: Greeter; greeter1 = new Greeter(); alert(greeter1.greet()); // 上下代码效果做对比 var greeterMaker: typeof Greeter = Greeter; greeterMaker.standardGreeting = "Hey there!"; var greeter2:Greeter = new greeterMaker(); alert(greeter2.greet()); 在这个例子中,"greeter1"和之前例子是一样的。我们实例化了"Greeter"类,并且使用这个对象。结果也和之前的例子一样。 将类当作接口一样使用 |
|
来自: 昵称10504424 > 《工作》