TypeScript - 抽象类
你好,有抱负的程序员们!今天,我们将踏上一段激动人心的旅程,探索TypeScript的世界,并深入了解其强大的特性之一:抽象类。如果你是编程新手,不用担心;我会一步步引导你理解这个概念,就像我多年来教导无数学生一样。那么,让我们开始吧!
什么是抽象类?
在我们深入了解抽象类之前,先用一个简单的类比来理解。想象你在一个汽车经销商那里,看到了一个写着“车辆”的标志。现在,你实际上不能购买一个“车辆”,因为它太宽泛了。你需要选择一种具体的车辆类型,比如汽车、卡车或摩托车。在编程中,抽象类就像是那个一般的“车辆”概念 - 它是其他类的蓝图,但你不能直接从中创建一个对象。
TypeScript中的抽象类作为其他类可以继承的基类。它们可能包含抽象方法(没有主体的方法)和具体方法(有主体的方法)。要记住的关键点是,你不能直接创建抽象类的实例。
创建抽象类
现在,让我们看看如何在TypeScript中创建一个抽象类。我们在class
关键字之前使用abstract
关键字。以下是一个基本结构:
abstract class 类名 {
// 属性和方法放在这里
}
抽象方法
抽象类可以有抽象方法。这些是声明了但没有在抽象类中实现的方法。任何扩展此抽象类的类都必须为这些方法提供实现。
具体方法
抽象类也可以有具体方法,这些是完整实现的方法,可以被子类继承。
示例 1:Shape 抽象类
让我们创建一个简单的示例来演示抽象类的工作方式。我们将创建一个抽象的Shape
类,它有一个抽象方法calculateArea()
。
abstract class Shape {
color: string;
constructor(color: string) {
this.color = color;
}
abstract calculateArea(): number;
displayColor(): void {
console.log(`这个形状的颜色是 ${this.color}`);
}
}
在这个示例中:
-
Shape
是我们的抽象类。 -
color
是所有形状都将有的属性。 -
calculateArea()
是抽象方法。注意它没有主体,只有声明。 -
displayColor()
是一个具体方法,所有形状都可以使用。
现在,让我们创建一些扩展我们的Shape
类的具体形状:
class Circle extends Shape {
radius: number;
constructor(color: string, radius: number) {
super(color);
this.radius = radius;
}
calculateArea(): number {
return Math.PI * this.radius * this.radius;
}
}
class Rectangle extends Shape {
width: number;
height: number;
constructor(color: string, width: number, height: number) {
super(color);
this.width = width;
this.height = height;
}
calculateArea(): number {
return this.width * this.height;
}
}
现在我们可以使用这些类:
const circle = new Circle("红色", 5);
console.log(circle.calculateArea()); // 输出: 78.53981633974483
circle.displayColor(); // 输出: 这个形状的颜色是 红色
const rectangle = new Rectangle("蓝色", 4, 6);
console.log(rectangle.calculateArea()); // 输出: 24
rectangle.displayColor(); // 输出: 这个形状的颜色是 蓝色
在这个示例中,Circle
和Rectangle
都扩展了Shape
类,并提供了calculateArea()
方法的自己的实现。它们还从Shape
类继承了displayColor()
方法。
示例 2:Animal 抽象类
让我们再创建一个示例来加强我们的理解。这次,我们将创建一个抽象的Animal
类:
abstract class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
abstract makeSound(): void;
move(distance: number = 0): void {
console.log(`${this.name} 移动了 ${distance} 米。`);
}
}
class Dog extends Animal {
constructor(name: string) {
super(name);
}
makeSound(): void {
console.log("汪!汪!");
}
}
class Cat extends Animal {
constructor(name: string) {
super(name);
}
makeSound(): void {
console.log("喵!");
}
}
让我们使用这些类:
const dog = new Dog("Buddy");
dog.makeSound(); // 输出: 汪!汪!
dog.move(10); // 输出: Buddy 移动了 10 米。
const cat = new Cat("Whiskers");
cat.makeSound(); // 输出: 喵!
cat.move(5); // 输出: Whiskers 移动了 5 米。
在这个示例中,Animal
是我们的抽象类,它有一个抽象的makeSound()
方法和一个具体的方法move()
。Dog
和Cat
扩展了Animal
并提供了makeSound()
方法的自己的实现。
为什么使用抽象类?
你可能会想,“为什么要这么麻烦?为什么不直接使用普通类?” 嗯,抽象类在你想要为一系列相关类定义一个公共接口时非常有用。它们允许你:
- 为一组相关类定义一个共同的结构。
- 强制子类实现某些方法。
- 提供所有子类都可以使用的一些公共功能。
把它看作是创建一个模板或合同,其他类必须遵循。这是确保相关类之间一致性的方式,同时仍然允许在需要时进行定制。
抽象类中的方法
下面是一个总结抽象类中可以有哪些类型的方法的表格:
方法类型 | 描述 | 可以在抽象类上调用吗? | 子类必须实现吗? |
---|---|---|---|
抽象方法 | 声明但没有实现 | 否 | 是 |
具体方法 | 完全实现的方法 | 是 | 否(可以被覆盖) |
结论
好了,各位!我们已经穿越了TypeScript中抽象类的领域。从理解它们是什么,到创建它们,再到用真实世界的示例看到它们的作用,你现在对这个强大的TypeScript特性有了坚实的基础。
记住,抽象类就像是建筑的蓝图。它们提供了结构和一些细节,但是扩展它们的类需要填充具体细节并将它们变为现实。
在你继续编程之旅时,你会发现抽象类是你TypeScript工具箱中非常有用的工具。它们帮助你编写更干净、更有组织、更易于维护的代码。所以,大胆地去抽象吧!
快乐编码,下次见,继续探索和学习!
Credits: Image by storyset