本文将会深入讨论 TypeScript 中的面向对象编程相关的特性,包括:
-
类的定义和使用
-
继承和多态
-
抽象类和接口
-
泛型和类型约束
-
装饰器
类的定义和使用
在 TypeScript 中,我们可以使用 class
关键字来定义类:
class Person {
private name: string;
private age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
getName(): string {
return this.name;
}
getAge(): number {
return this.age;
}
}
const person = new Person('张三', 18);
console.log(person.getName()); // 输出:张三
console.log(person.getAge()); // 输出:18
在上述代码中,我们定义了一个 Person
类,该类有两个私有属性 name
和 age
,并且有一个构造函数用于初始化这两个属性。类中还有两个公共方法 getName
和 getAge
,用于获取属性值。在创建类的实例时,需要使用 new
关键字,并传入构造函数所需的参数。
继承和多态
继承是面向对象编程中的重要概念,它可以用于复用代码和构建类层次结构。在 TypeScript 中,我们可以使用 extends
关键字实现继承:
class Animal {
protected name: string;
constructor(name: string) {
this.name = name;
}
move(distance: number = 0): void {
console.log(`${this.name} moved ${distance}m.`);
}
}
class Dog extends Animal {
bark(): void {
console.log('Woof! Woof!');
}
}
const dog = new Dog('旺财');
dog.move(10); // 输出:旺财 moved 10m.
dog.bark(); // 输出:Woof! Woof!
在上述代码中,我们定义了一个 Animal
类,它有一个受保护的属性 name
和一个公共方法 move
,并且有一个默认值为 0 的参数 distance
。Dog
类继承自 Animal
类,并且有一个独有的方法 bark
。在创建 Dog
类的实例时,既可以使用从父类继承的 move
方法,也可以使用自己独有的 bark
方法,这就是多态。
抽象类和接口
抽象类和接口是面向对象编程中的两个重要概念,它们分别用于描述类和对象的共性和特性。在 TypeScript 中,我们可以使用 abstract
关键字定义抽象类,并且使用 implements
关键字实现接口。
interface Animal {
name: string;
move(distance: number): void;
}
abstract class Shape {
abstract getArea(): number;
}
class Rectangle extends Shape {
private width: number;
private height: number;
constructor(width: number, height: number) {
super();
this.width = width;
this.height = height;
}
getArea(): number {
return this.width * this.height;
}
}
class Elephant implements Animal {
name: string;
constructor(name: string) {
this.name = name;
}
move(distance: number): void {
console.log(`${this.name} moved ${distance}m.`);
}
}
const rect = new Rectangle(10, 20);
console.log(rect.getArea()); // 输出:200
const elephant = new Elephant('大象');
elephant.move(50); // 输出:大象 moved 50m.
在上述代码中,我们使用 interface
关键字定义了一个 Animal
接口,它有两个属性 name
和 move
。另外,我们使用 abstract
关键字定义了一个抽象类 Shape
,该类有一个抽象方法 getArea
,并且该类不能被实例化。Rectangle
类继承自 Shape
类,并且实现了 getArea
方法。Elephant
类实现了 Animal
接口,并且重写了 move
方法。在创建不同类型的对象时,分别使用了相应的类或接口,并进行了相应的操作。
泛型和类型约束
泛型是 TypeScript 中的一项强大特性,它可以让函数和类接收任意类型的参数,在编译时确定参数和返回值的类型。在 TypeScript 中,我们可以使用尖括号来表示泛型,并使用类型约束(extends)来限制泛型的类型。
function identity<T extends string | number>(arg: T): T {
return arg;
}
console.log(identity<string>('hello')); // 输出:hello
console.log(identity<number>(123)); // 输出:123
在上述代码中,我们定义了一个泛型函数 identity
,它接收一个类型为 T
的参数 arg
,并将该参数原封不动地返回。为了限制 T
的类型,我们使用了类型约束 extends
,限制 T
只能是 string
或 number
类型。在调用函数时,使用尖括号来指定泛型的具体类型。
装饰器
装饰器是 TypeScript 中的一个实验性特性,它可以用于在编译时修改类和方法的行为。在 TypeScript 中,我们可以使用 @decorator
的形式来应用装饰器,其中 decorator
是一个函数。
function log(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const method = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`调用 ${propertyKey} 方法`);
const result = method.apply(this, args);
console.log(`返回值为 ${result}`);
return result;
}
return descriptor;
}
class Calculator {
@log
add(a: number, b: number): number {
return a + b;
}
}
const calculator = new Calculator();
console.log(calculator.add(1, 2)); // 输出:调用 add 方法,返回值为 3
在上述代码中,我们定义了一个 log
装饰器函数,该函数接收三个参数:类的原型对象 target
、方法名 propertyKey
和方法描述符 descriptor
。在装饰器函数中,我们修改了方法的行为,在方法执行前打印了一句日志,方法执行后打印了返回值,并返回修改后的方法描述符。另外,我们使用装饰器 @log
来应用装饰器函数,该装饰器应用于类的 add
方法上。在创建 Calculator
类的实例时,调用 add
方法并输出结果,可以看到已经使用了装饰器修改了方法的行为。
结论
TypeScript 中的面向对象编程相关的特性比较多,其中包括类的定义和使用、继承和多态、抽象类和接口、泛型和类型约束、装饰器等。这些特性可以让开发者更加方便地进行面向对象编程,并且可以使得代码更加具有可读性、可维护性和可扩展性。在使用这些特性时,需要遵循 TypeScript 的类型约束和面向对象编程的思想,并根据项目需求进行选择和应用。