[TypeScript][文档]类
一、继承
class Animal { name: string; constructor(theName: string) { this.name = theName; } 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); } } class Horse extends Animal { constructor(name: string) { super(name); } move(distanceInMeters = 45) { console.log("Galloping..."); super.move(distanceInMeters); } } let sam = new Snake("Sammy the Python"); let tom: Animal = new Horse("Tommy the Palomino"); sam.move(); tom.move(34);
【注】:子类的构造方法中,必须首先调用super(),这是强制执行的规则。
二、public、private、protected
1.public 公有
TypeScript中,成员默认为public
2.private 私有
当成员被标记成 private
时,它就不能在声明它的类的外部访问,但是如果它被继承,子类里面还是有这个成员的,只是不能访问。
class Animal { private name: string; constructor(theName: string) { this.name = theName; } } new Animal("Cat").name; // 错误: 'name' 是私有的.
3.protected 保护
protected
修饰符与 private
修饰符的行为很相似,但有一点不同, protected
成员在派生类中仍然可以访问。
【注】:构造函数也可以被标记成 protected
。 这意味着这个类不能在包含它的类外被实例化,但是能被继承。
三、reanonly和参数属性
1.readonly
可以使用 readonly
关键字将属性设置为只读的。 只读属性必须在声明时或构造函数里被初始化。
class Octopus { readonly name: string; readonly numberOfLegs: number = 8; constructor (theName: string) { this.name = theName; } } let dad = new Octopus("Man with the 8 strong legs"); dad.name = "Man with the 3-piece suit"; // 错误! name 是只读的.
2.参数属性
参数属性通过给构造函数参数前面添加一个访问限定符来声明。 就是说在构造函数里面直接定义成员变量。
class Octopus { readonly numberOfLegs: number = 8; constructor(readonly name: string) { } }
四、存取器
存取器用来控制对对象成员的访问,即必须符合一定的规则才能进行访问(get)或者修改(set)。
存取器对于对象内部来说类似于一个方法,对于对象外部则类似于一个成员变量。
一般把成员声明为私有,使用get 和 set 来控制在一定条件下的存取。
let 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 { console.log("Error: Unauthorized update of employee!"); } } } let employee = new Employee(); employee.fullName = "Bob Smith"; // 对外则相当于一个成员变量,并且只有满足条件才能修改 if (employee.fullName) { alert(employee.fullName); }
【注】:只带有 get
不带有 set
的存取器自动被推断为 readonly
五、静态属性
静态属性用static修饰,属于类而不是类的实例,访问时使用 类名.属性
六、抽象类
抽象类做为其它派生类的基类使用。 它们一般不会直接被实例化。 不同于接口,抽象类可以包含成员的实现细节。
abstract class Department { constructor(public name: string) { } printName(): void { console.log('Department name: ' + this.name); } abstract printMeeting(): void; // 必须在派生类中实现 } class AccountingDepartment extends Department { constructor() { super('Accounting and Auditing'); // 在派生类的构造函数中必须调用 super() } printMeeting(): void { console.log('The Accounting Department meets each Monday at 10am.'); } generateReports(): void { console.log('Generating accounting reports...'); } } let department: Department; // 允许创建一个对抽象类型的引用 department = new Department(); // 错误: 不能创建一个抽象类的实例 department = new AccountingDepartment(); // 允许对一个抽象子类进行实例化和赋值 department.printName(); department.printMeeting(); department.generateReports(); // 错误: 方法在声明的抽象类中不存在
七、高级技巧
1.类的实例类型
let greeter: Greeter; greeter = new Greeter("world");
这里,我们写了 let greeter: Greeter
,意思是 Greeter
类的实例的类型是 Greeter
。