TypeScript 类和对象
类(Class)是面向对象编程(OOP)的核心概念,它是创建对象的蓝图。TypeScript 全面支持 ES6 中引入的类语法,并在此基础上添加了类型注解、访问修饰符等特性。
什么是类和对象?
- 类 (Class): 一个模板或蓝图,用于描述一类对象的共同属性(数据)和行为(方法)。
- 对象 (Object): 类的一个实例。通过
new关键字创建,拥有类所定义的属性和方法。
定义一个类
下面是一个简单的类定义:
typescript
class Greeter {
// 属性 (Property)
greeting: string;
// 构造函数 (Constructor)
constructor(message: string) {
this.greeting = message;
}
// 方法 (Method)
greet() {
return "Hello, " + this.greeting;
}
}
// 创建类的实例(一个对象)
let greeter = new Greeter("world");
console.log(greeter.greet()); // "Hello, world"继承 (Inheritance)
继承是允许一个类(子类)获取另一个类(父类)的属性和方法的一种机制。使用 extends 关键字来实现继承。
typescript
class Animal {
name: string;
constructor(theName: string) { this.name = theName; }
move(distanceInMeters: number = 0) {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}
// Snake 是 Animal 的子类
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();
// Slithering...
// Sammy the Python moved 5m.super(): 在子类的构造函数中,必须调用super()来执行父类的构造函数。super.method(): 可以用来调用父类中被重写(override)的方法。
访问修饰符 (Access Modifiers)
TypeScript 提供了三种访问修饰符,用于控制类成员(属性和方法)的可访问性。
public(默认): 成员可以在任何地方被访问。如果你不指定修饰符,它默认为public。private: 成员只能在声明它的类内部被访问。子类和类的实例都无法访问。typescriptclass Person { private name: string; constructor(name: string) { this.name = name; } public greet() { console.log(`Hello, my name is ${this.name}`); } } let john = new Person("John"); john.greet(); // OK // console.log(john.name); // Error: Property 'name' is private.protected: 成员可以在声明它的类以及该类的子类中被访问,但不能在类的实例上访问。typescriptclass Employee extends Person { private department: string; constructor(name: string, department: string) { super(name); this.department = department; } public getElevatorPitch() { // 可以在子类中访问父类的 protected 成员 // return `Hello, my name is ${this.name} and I work in ${this.department}.`; // 如果 name 是 protected,上面这行是 OK 的。如果是 private,则会报错。 } }
只读修饰符 (readonly)
readonly 关键字可以确保属性在声明时或构造函数中被初始化后,不能再被修改。
typescript
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"; // Error! name is readonly.静态属性和方法 (static)
静态成员属于类本身,而不是类的实例。你可以直接通过类名来访问它们,而不需要创建对象。
typescript
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) { }
}
console.log(Grid.origin); // { x: 0, y: 0 }
let grid1 = new Grid(1.0);抽象类 (abstract)
抽象类是作为其他类的基类的。它们不能被直接实例化。抽象类中可以包含抽象方法,这些方法没有具体的实现,必须在派生类中被实现。
typescript
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");
}
printMeeting(): void {
console.log("The Accounting Department meets each Monday at 10am.");
}
}
let department: Department; // 允许创建一个对抽象类型的引用
// department = new Department(); // 错误: 不能创建一个抽象类的实例
department = new AccountingDepartment(); // 允许对一个抽象子类进行实例化和赋值
department.printName();
department.printMeeting();