指南

类与面向对象编程

详解 TS 中类与面向对象编程的核心概念,区别 ES6 和 TS 特性的分界线

🎯 引言

学完这篇文章,你能清楚分辨 ES6 和 TS 中类与面向对象编程的异同,能够用 TS 编写规范的面向对象代码。你会了解类定义、访问修饰符、继承与实现、抽象类与接口等基础知识,并知道哪些是 ES6 支持的,哪些是 TS 独有的特性。


✨ class 定义与构造函数

在 ES6 之前,JavaScript 主要基于原型链实现面向对象。ES6 引入了 class 关键字,让我们像传统面向对象语言那样定义类。TS 对 ES6 的类进行了增强和类型约束。

// ES6 的类定义及构造函数
class Person {
    constructor(name) {
        this.name = name;
    }

    sayHello() {
        console.log('Hello, ' + this.name);
    }
}

const p = new Person('小红');
p.sayHello();

以上代码是 ES6 支持的。TS 也是这样写类的,但可以加上类型声明,让代码更严谨:

// TS 类定义,带类型
class Person {
    name: string;

    constructor(name: string) {
        this.name = name;
    }

    sayHello(): void {
        console.log('Hello, ' + this.name);
    }
}

const p = new Person('小红');
p.sayHello();
TS 中类的成员变量和方法都可以加类型声明,帮助在编译时发现错误。

🔐 public、private、protected 访问修饰符

这是 TS 在类上的独家特性。ES6 本身不支持访问修饰符,所有属性和方法默认都是公开的。

  • public 表示公有,可以从类外访问(TS 默认就是 public
  • private 表示私有,只能在类内部访问
  • protected 表示受保护,只能在类内部和子类访问
class Person {
    public name: string; // 公有属性
    private age: number; // 私有属性
    protected gender: string; // 受保护属性

    constructor(name: string, age: number, gender: string) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    public sayHello(): void {
        console.log(`Hi, I'm ${this.name}`);
    }

    private getAge(): number {
        return this.age;
    }
}
访问修饰符只在 TS 编译阶段起作用,编译成 JS 后并不会真的限制访问,但可以强制大家遵守访问规则。

🧬 继承与实现

继承是 ES6 也支持的基本特性。用 extends 关键字实现子类继承父类。

// ES6 继承示例
class Animal {
    constructor(name) {
        this.name = name;
    }
    move() {
        console.log(this.name + ' 在移动');
    }
}

class Dog extends Animal {
    bark() {
        console.log('汪汪');
    }
}

const dog = new Dog('小白');
dog.move();
dog.bark();

TS 继承写法类似,但可以加类型声明:

class Animal {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
    move(): void {
        console.log(this.name + ' 在移动');
    }
}

class Dog extends Animal {
    bark(): void {
        console.log('汪汪');
    }
}

const dog = new Dog('小白');
dog.move();
dog.bark();

实现(Implement)接口

实现接口是 TS 独有的概念,ES6 没有接口。接口用于定义类必须实现的属性和方法,属于静态类型检查。

interface Flyable {
    fly(): void;
}

class Bird implements Flyable {
    fly(): void {
        console.log('我会飞');
    }
}

如果类没有实现接口中的所有方法,TS 会报错。

接口用来规范类的结构,类似合同,确保类符合预期功能。

🏗 抽象类与接口

抽象类

抽象类是 TS 独有的概念,ES6 不支持。

抽象类不能直接实例化,通常用于作为基类,定义子类必须实现的方法。

abstract class Animal {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
    abstract makeSound(): void; // 抽象方法,必须由子类实现

    move(): void {
        console.log(this.name + ' 在移动');
    }
}

class Cat extends Animal {
    makeSound(): void {
        console.log('喵喵');
    }
}

const cat = new Cat('小花');
cat.makeSound();

接口

接口定义了类的外部形状,不包含具体实现。一个类可以实现多个接口。

interface Swimmer {
    swim(): void;
}

interface Flyer {
    fly(): void;
}

class Duck implements Swimmer, Flyer {
    swim(): void {
        console.log('鸭子游泳');
    }
    fly(): void {
        console.log('鸭子飞翔');
    }
}

🧾 小节总结

  • ES6 原生支持类定义、构造函数和继承(classconstructorextends),但不支持访问修饰符、接口和抽象类。
  • TS 在 ES6 类基础上添加了访问修饰符(publicprivateprotected),接口(interface),抽象类(abstract class)等强类型和面向对象的特性。
  • 接口和抽象类是 TS 独有的,可以用来规范代码结构和抽象行为,增加代码的可维护性。

❓ 知识问答(Q&A)

Q:ES6 中的类和 TS 类最大的区别是什么?

A:ES6 仅支持类的基本语法和继承关系,TS 在此基础上增加了访问修饰符、类型声明、接口和抽象类等面向对象特性。

Q:访问修饰符在编译后的 JS 代码中是否有效?

A:访问修饰符只在 TS 编译阶段生效,编译成 JS 后不存在访问限制,但开发时提示错误,保证代码规范。

Q:接口和抽象类有什么不同?

A:接口只定义规范,没有具体实现,类可以实现多个接口;抽象类可以包含具体实现和抽象方法,不能实例化,只能被继承。


🧪 小练习

练习 1

写一个 Vehicle 抽象类,包含一个抽象方法 move(),和一个普通方法 stop()。然后写一个 Car 类继承 Vehicle 并实现 move() 方法。

abstract class Vehicle {
    abstract move(): void;
    stop(): void {
        console.log('停止');
    }
}

// 在这里写 Car 类,继承 Vehicle 并实现 move()

练习 2

定义一个接口 Playable,包含方法 play(), 写一个类 Music 实现这个接口,并在 play() 方法中输出播放音乐的提示。

interface Playable {
    play(): void;
}

// 写 Music 类,实现 Playable 接口

🎉 恭喜你已经掌握 TS 类定义、访问修饰符、继承与实现、抽象类与接口技能啦! 面向对象的思想能帮助你写出更结构化、可维护的代码,TS 的类型系统让这个过程更可靠。继续练习,你会更得心应手!