在面向对象编程中,类(Class)是组织代码的重要结构。TypeScript 在 JavaScript 的基础上增强了类的功能,支持类型检查、访问控制、继承、抽象等高级特性,使得代码更具结构性和可维护性。
本文将带你全面了解 TypeScript 中的类机制,包括:
✅ 类的基本定义与使用
✅ 构造函数与属性初始化
✅ 访问修饰符 public
/ private
/ protected
✅ 静态成员与只读属性
✅ 继承与多态
✅ 抽象类与接口实现
✅ 实际开发中的最佳实践
并通过完整的代码示例帮助你掌握如何用类构建复杂应用。
类是一种模板或蓝图,用于创建具有相同属性和行为的对象。它封装了数据(属性)和操作数据的方法。
⚠️ TypeScript 中的类不仅支持传统的面向对象特性,还增加了类型系统支持,使开发更安全、更高效。
class Person {
name: string;
constructor(name: string) {
this.name = name;
}
sayHello(): void {
console.log(`Hello, my name is ${this.name}`);
}
}
const person = new Person("Alice");
person.sayHello(); // 输出:Hello, my name is Alice
class Person {
constructor(public name: string, private age: number) {}
}
上面的写法相当于:
class Person {
name: string;
private age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
修饰符 | 可见范围 | 说明 |
---|---|---|
public |
所有地方 | 默认修饰符,公开访问 |
private |
本类内部 | 不可在子类或外部访问 |
protected |
本类及子类 | 不可在外部访问 |
class Animal {
public name: string;
private secret: string;
protected id: number;
constructor(name: string, secret: string, id: number) {
this.name = name;
this.secret = secret;
this.id = id;
}
}
class Dog extends Animal {
showId() {
console.log(this.id); // ✅ 子类可以访问 protected 成员
// console.log(this.secret); ❌ 编译错误,不能访问 private 成员
}
}
const a = new Animal("Cat", "meow", 1);
console.log(a.name); // ✅ 公共属性可以访问
// console.log(a.secret); ❌ 私有属性不可访问
// console.log(a.id); ❌ 受保护属性不可访问
静态成员属于类本身,而不是类的实例。
class MathUtils {
static PI = 3.14159;
static calculateCircleArea(radius: number): number {
return this.PI * radius * radius;
}
}
console.log(MathUtils.calculateCircleArea(5)); // 输出:78.53975
readonly
readonly
修饰符表示该属性只能在声明时或构造函数中被赋值。
class User {
readonly id: number;
constructor(id: number) {
this.id = id;
}
}
const user = new User(1);
// user.id = 2; ❌ 报错:无法修改只读属性
class Animal {
makeSound(): void {
console.log("Some sound");
}
}
class Dog extends Animal {
override makeSound(): void {
console.log("Woof!");
}
}
const dog = new Dog();
dog.makeSound(); // 输出:Woof!
function playSound(animal: Animal) {
animal.makeSound();
}
playSound(new Animal()); // Some sound
playSound(new Dog()); // Woof!
抽象类不能直接实例化,必须通过子类继承并实现抽象方法。
abstract class Shape {
abstract getArea(): number;
}
class Circle extends Shape {
constructor(private radius: number) {
super();
}
getArea(): number {
return Math.PI * this.radius * this.radius;
}
}
const circle = new Circle(5);
console.log(circle.getArea()); // 输出:78.53981633974483
类可以实现一个或多个接口,以保证其具备某些特定的行为。
interface ILogger {
log(message: string): void;
}
class ConsoleLogger implements ILogger {
log(message: string): void {
console.log(`[LOG] ${message}`);
}
}
const logger = new ConsoleLogger();
logger.log("This is a log message."); // 输出:[LOG] This is a log message.
class User {
constructor(
public id: number,
public username: string,
private password: string
) {}
login(inputPassword: string): boolean {
return inputPassword === this.password;
}
}
const user = new User(1, "admin", "123456");
console.log(user.login("wrong")); // false
console.log(user.login("123456")); // true
abstract class Shape {
abstract getArea(): number;
}
class Rectangle extends Shape {
constructor(private width: number, private height: number) {
super();
}
getArea(): number {
return this.width * this.height;
}
}
class Circle extends Shape {
constructor(private radius: number) {
super();
}
getArea(): number {
return Math.PI * this.radius * this.radius;
}
}
function printArea(shape: Shape) {
console.log(`Area: ${shape.getArea()}`);
}
printArea(new Rectangle(4, 5)); // Area: 20
printArea(new Circle(3)); // Area: 28.274333882308138
场景 | 建议 |
---|---|
是否推荐使用 private |
✅ 推荐用于隐藏敏感数据 |
是否允许修改 readonly 属性 |
❌ 否,只能在构造函数中赋值 |
如何避免类膨胀? | ✅ 使用组合代替继承 |
抽象类 vs 接口? | ✅ 抽象类适合共享逻辑,接口适合定义契约 |
是否推荐使用 override 关键字? |
✅ 推荐,增强代码可读性和安全性 |
特性 | 示例 | 说明 |
---|---|---|
构造函数 | constructor() |
初始化对象 |
访问修饰符 | public , private , protected |
控制访问权限 |
静态成员 | static PI = 3.14 |
属于类而非实例 |
只读属性 | readonly id: number |
不可变属性 |
抽象类 | abstract class Shape |
必须被继承实现 |
接口实现 | implements ILogger |
强制实现特定方法 |
继承与重写 | extends , override |
支持多态 |
多态调用 | 函数接受父类引用 | 根据实际类型执行不同方法 |
感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!