类的注解方式
| class Animal { name: string; constructor(theName: string) { this.name = theName; } move(distanceInMeters: number = 0) { console.log(`${this.name} moved ${distanceInMeters}m.`); } }
|
继承中 super
// 注意这个 super, 如果在 constructor 内就是默认指 构造函数 。
// 如果在 constructor 外部(除了 constructor),这个 super 就是指的 父类 (Animal)。
| class Snake extends Animal { constructor(name: string) { super(name); } move(distanceInMeters = 5) { console.log('Slithering...'); super.move(distanceInMeters); } }
|
类的修饰符
三大类成员修饰符: public / private / protected
public
// 在 TypeScript 里,成员都默认为 public。
// 如果类默认不写, 就是 public
public : 公共成员属性
| class Animal { public name: string; public constructor(theName: string) { this.name = theName; } public move(distanceInMeters: number) { console.log(`${this.name} moved ${distanceInMeters}m.`); } }
|
private
// private : 私有属性
// 当我把 Animal 类中的 构造函数变成私有, 如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| class Animal { public name: string; private constructor(theName: string) { this.name = theName; } public move(distanceInMeters: number = 0) { console.log(`${this.name} moved ${distanceInMeters}m.`); } }
class Snake extends Animal { constructor(name: string) { super(name); } move(distanceInMeters = 5) { console.log('Slithering...'); super.move(distanceInMeters); } }
let sam = new Snake('Sammy the Python'); sam.move();
|
因此 , 可证明 private 只能自身调用, 子类和实例不能调用.
protected
protected 修饰符与 private 修饰符的行为很相似,但有一点不同, protected 成员在派生类中仍然可以访问。
也就是说 protected 可以自身调用,也可以子类调用.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| class Animal { public name: string; public constructor(theName: string) { this.name = theName; } protected move(distanceInMeters: number = 0) { console.log(`${this.name} moved ${distanceInMeters}m.`); } }
class Snake extends Animal { constructor(name: string) { super(name); } move(distanceInMeters = 5) { console.log('Slithering...'); super.move(distanceInMeters); } }
let jack = new Animal('jack'); jack.move();
|
这时,在编辑器上, 实例调用 move 方法会报错,
readonly(只读)修饰符
| class Octopus { public readonly name: string; private readonly numberOfLegs: number = 8; constructor(theName: string) { this.name = theName; } say() { console.log('hi'); } } let dad = new Octopus('Man with the 8 strong legs'); dad.name = 'Man with the 3-piece suit';
|
readonly 注意事项:
- 顺序: 要放在 public/private/protected 之后
- 是否可写: 加上 readonly 表示 只读,不可写
- 不能修饰成员方法.
参数属性
简写写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class Animal1 { constructor(private name: string) {} move(distanceInMeters: number = 0) { console.log(`${this.name} moved ${distanceInMeters}m.`); } }
class Animal2 { private name: string; constructor(name: string) { this.name = name; } move(distanceInMeters: number = 0) { console.log(`${this.name} moved ${distanceInMeters}m.`); } }
|
存取器
大概看了一下, 其实就是 getter 和 setter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| let passcode = 'secret passcode';
class Employee { private _fullName: string = 'jack';
get fullName(): string { return this._fullName; }
set fullName(newName: string) { if (passcode && passcode == 'secret passcode') { this._fullName = newName; } else { console.log('Error: Unauthorized update of employee!'); } } }
let employee = new Employee(); console.log(employee.fullName);
console.log((employee.fullName = 'new jack'));
|
静态属性
这个也是 不属于 TS 新有的知识, 学到这里,我发现其实我们大都是还是在复习 JS, 要学好 TS 前提是 JS 基础一定要好啊
| class Grid { static origin = { x: 0, y: 0 }; calculateDistanceFromOrigin(point: { x: number; y: number }) { let xDist = point.x - Grid.origin.x; let yDist = point.y - Grid.origin.y; return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale; } constructor(public scale: number) {} }
let grid1 = new Grid(1.0); let grid2 = new Grid(5.0);
console.log(grid1.calculateDistanceFromOrigin({ x: 10, y: 10 })); console.log(grid2.calculateDistanceFromOrigin({ x: 10, y: 10 }));
|
抽象类
抽象类: 能够提供其他类的基类 , 它们一般不会直接被实例化
抽象类:
- 无法创建实例
- 在抽象类中 抽象方法一定要实现 (这一点和接口很像)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| abstract class Animal { abstract makeSound(): void; move(): void { console.log('我在移动'); } }
class Dog extends Animal { makeSound() { console.log('汪汪汪'); } }
class Cat extends Animal { makeSound() { console.log('喵喵喵'); } }
|
高阶技巧
- 定义类的时候, 定义了一个类型;
- 定义类的时候, 定义了一个构造函数;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class Greeter { static standardGreeting = 'Hello, there'; greeting: string; greet() { if (this.greeting) { return 'Hello, ' + this.greeting; } else { return Greeter.standardGreeting; } } }
let greeter1: Greeter; greeter1 = new Greeter(); console.log(greeter1.greet());
let greeterMaker: typeof Greeter = Greeter; greeterMaker.standardGreeting = 'Hey there!';
let greeter2: Greeter = new greeterMaker(); console.log(greeter2.greet());
|
- 把类当做接口使用
| class Point { x: number; y: number; }
interface Point3d extends Point { z: number; }
let point3d: Point3d = { x: 1, y: 2, z: 3 };
|