类
类的继承
当派生类中有 constructor 构造函数的时候,一定要调用 super()->执行基类的构造函数。在派生类中使用 this 之前一定要使用 super()
class Animal {
name: string;
constructor(theName: string) {
this.name = theName;
}
move(name: string) {
console.log(`${name}说:我能移动`);
}
}
class Dog extends Animal {
constructor(name: string) {
super(name);
}
bark() {
console.log(`${this.name}我能狂叫`);
}
move() {
//子类的方法会覆盖父类的方法
console.log(`${this.name}说我自己能移动`);
super.move(this.name); // 调用基类的move方法
}
}
let dog = new Dog('花花');
dog.bark();
dog.move();
公有、私有与受保护修饰符
- public(公有) ->默认值 js 中可写可不写
- private(私有)
- protected(在派生类中可以访问)
- readonly(只读属性)
比较带有 private 或 protected 成员的类型的时候,情况就不同了。 如果其中一个类型里包含一个 private 成员,那么只有当另外一个类型中也存在这样一个 private 成员, 并且它们都是来自同一处声明时,才认为这两个类型是兼容的。 对于 protected 成员也使用这个规则。
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; }
}
let animal = new Animal("Goat");
let rhino = new Rhino();
let employee = new Employee("Bob");
animal = rhino;
animal = employee; // 错误: Animal 与 Employee 不兼容.
protected 成员类型只能访问不能被使用,构造函数也可以被标记成 protected。 这意味着这个类不能在包含它的类外被实例化,但是能被继承。
只读属性只能在 constructor 函数中被初始化。
静态属性
静态属性存在于类本身上面而不是类的实例上,可以通过类名.属性来访问。
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); // 1x scale
let grid2 = new Grid(5.0); // 5x scale
console.log(grid1.calculateDistanceFromOrigin({x: 10, y: 10}));
console.log(grid2.calculateDistanceFromOrigin({x: 10, y: 10}));
抽象类
抽象类做为其它派生类的基类使用。 它们一般不会直接被实例化。 不同于接口,抽象类可以包含成员的实现细节。使用 abstract 关键字定义。抽象类中的抽象方法不包含具体实现并且必须在派生类中实现
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(); // 错误: 方法在声明的抽象类中不存在
把类当做接口使用
类定义会创建两个东西:类的实例类型和一个构造函数。 因为类可以创建出类型,所以你能够在允许使用接口的地方使用类。
class Point {
x: number;
y: number;
}
interface Point3d extends Point {
z: number;
}
let point3d: Point3d = { x: 1, y: 2, z: 3 };