现在位置: 首页 > TypeScript 教程 > 正文

TypeScript 类

类是面向对象编程(OOP)的核心概念,它是一种模板或蓝图,用于创建具有相同属性和方法的对象。TypeScript 完全支持面向对象编程,提供了类、继承、访问修饰符等特性。

类封装了数据(属性)和行为(方法),使得代码更加模块化、可复用和易维护。通过类,我们可以创建多个具有相同结构的对象,这些对象称为类的实例。


类的定义

TypeScript 使用 class 关键字定义类。一个类可以包含以下成员:

  • 字段(Field):类中声明的变量,表示对象的属性
  • 构造函数(Constructor):类实例化时调用的特殊方法,用于初始化对象
  • 方法(Method):类中定义的函数,表示对象的行为

语法格式

class class_name {
    // 字段声明
    field1: type;
    field2: type;

    // 构造函数
    constructor(parameters) {
        // 初始化代码
    }

    // 方法
    methodName(): return_type {
        // 方法实现
    }
}

实例:创建简单的类

实例

// 定义一个空的 Person 类
class Person {
}

编译后的 JavaScript:

实例

var Person = /** @class */ (function () {
    function Person() {
    }
    return Person;
}());

类的字段和构造函数

类的字段是存储对象数据的地方,构造函数在对象创建时自动调用,用于初始化字段。

实例

// 定义 Car 类
class Car {
    // 字段:描述汽车的属性
    engine: string;

    // 构造函数:在创建对象时初始化 engine
    constructor(engine: string) {
        this.engine = engine;
    }

    // 方法:显示发动机信息
    disp(): void {
        console.log("发动机型号: " + this.engine);
    }
}

// 创建类的实例
var car = new Car("V8 发动机");

// 访问字段
console.log("读取发动机: " + car.engine);

// 调用方法
car.disp();

运行结果:

读取发动机: V8 发动机
发动机型号: V8 发动机

说明:

  • this 关键字指向当前类的实例
  • 构造函数的参数名可以与字段名相同,通过 this.field 区分
  • 使用 new 关键字创建类的实例

注意:TypeScript 的类在编译后会转换为 JavaScript 的构造函数原型模式,接口不会出现在编译结果中。


访问控制修饰符

TypeScript 提供了三种访问修饰符来控制类成员的可访问性:

修饰符 说明
public 公有成员,可以在任何地方访问(默认)
private 私有成员,只能在类内部访问
protected 受保护成员,可以在类内部和子类中访问

public(默认)

实例

class Person {
    public name: string;    // 公有属性
    public age: number;     // 公有属性

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

    public introduce(): void {
        console.log("我是 " + this.name + ",今年 " + this.age + " 岁");
    }
}

var person = new Person("Alice", 25);
console.log("姓名: " + person.name);   // 可以访问
person.introduce();                    // 可以访问

private(私有)

实例

class Person {
    public name: string;
    private secret: string;  // 私有属性,外部无法直接访问

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

    // 公有方法可以访问私有属性
    public revealSecret(): void {
        console.log("秘密: " + this.secret);
    }
}

var person = new Person("Alice", "我喜欢编程");

console.log("姓名: " + person.name);   // 可以访问
// console.log(person.secret);        // 错误:'secret' 是私有属性

person.revealSecret();                 // 通过公有方法访问私有属性

protected(受保护)

实例

class Person {
    protected name: string;  // 受保护属性

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

    protected sayHello(): void {
        console.log("你好,我是 " + this.name);
    }
}

class Student extends Person {
    private grade: string;

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

    public introduce(): void {
        // 子类可以访问受保护的属性和方法
        console.log("我是 " + this.name + ",年级: " + this.grade);
        this.sayHello();
    }
}

var student = new Student("Bob", "高三");
student.introduce();    // 可以访问

// console.log(student.name);  // 错误:'name' 是受保护属性

运行结果:

我是 Bob,年级: 高三
你好,我是 Bob

类的继承

继承允许创建一个类(子类)从另一个类(父类)获取属性和方法。子类可以复用父类的代码,还可以扩展或重写父类的行为。

基本语法

class child_class extends parent_class {
    // 子类新增的属性和方法
}

单继承

实例

// 父类:形状
class Shape {
    area: number;

    constructor(a: number) {
        this.area = a;
    }
}

// 子类:圆,继承自 Shape
class Circle extends Shape {
    disp(): void {
        console.log("圆的面积: " + this.area);
    }
}

var circle = new Circle(223);
circle.disp();

运行结果:

圆的面积: 223

多重继承

TypeScript 不支持多继承(一个类继承多个类),但支持多层继承(A 继承 B,B 继承 C):

实例

// 根类
class Root {
    str: string;
}

// 子类:继承 Root
class Child extends Root {
}

// 叶子类:继承 Child(多重继承)
class Leaf extends Child {
}

var leaf = new Leaf();
leaf.str = "hello";
console.log("str 值: " + leaf.str);

运行结果:

str 值: hello

方法重写(Override)

子类可以重写(Override)父类的方法,即在子类中定义与父类同名的方法,实现自己的行为。

使用 super 关键字可以调用父类的方法。

实例

// 父类
class PrinterClass {
    doPrint(): void {
        console.log("父类的 doPrint() 方法");
    }
}

// 子类:重写父类方法
class StringPrinter extends PrinterClass {
    doPrint(): void {
        // 调用父类的方法
        super.doPrint();

        // 子类自己的逻辑
        console.log("子类的 doPrint() 方法");
    }
}

var obj = new StringPrinter();
obj.doPrint();

运行结果:

父类的 doPrint() 方法
子类的 doPrint() 方法

静态成员

使用 static 关键字定义的成员属于类本身,而不是类的实例。可以直接通过类名访问,不需要创建实例。

实例

class StaticMem {
    // 静态属性
    static num: number;

    // 静态方法
    static disp(): void {
        console.log("num 值为 " + StaticMem.num);
    }
}

// 直接通过类名访问静态成员
StaticMem.num = 12;
StaticMem.disp();

运行结果:

num 值为 12

应用场景:静态成员常用于定义类的常量、工具方法或单例模式。


instanceof 运算符

instanceof 用于判断对象是否是某个类的实例。

实例

class Person {
}

var obj = new Person();
var isPerson = obj instanceof Person;

console.log("obj 是 Person 类的实例吗? " + isPerson);

运行结果:

obj 是 Person 类的实例吗? true

类实现接口

类可以使用 implements 关键字实现接口,确保类符合接口定义的契约。

实例

// 定义接口
interface ILoan {
    interest: number;  // 利率
}

// 类实现接口
class AgriLoan implements ILoan {
    interest: number;
    rebate: number;    // 回扣

    constructor(interest: number, rebate: number) {
        this.interest = interest;
        this.rebate = rebate;
    }
}

var loan = new AgriLoan(10, 1);
console.log("利率: " + loan.interest + "%,回扣: " + loan.rebate);

运行结果:

利率: 10%,回扣: 1

抽象类

抽象类不能被实例化,只能作为基类供子类继承。抽象类可以包含抽象方法(没有实现的占位方法),子类必须实现这些方法。

实例

// 抽象类
abstract class Animal {
    abstract makeSound(): void;  // 抽象方法,子类必须实现

    move(): void {
        console.log("动物在移动");
    }
}

// 具体类:继承抽象类
class Dog extends Animal {
    makeSound(): void {
        console.log("汪汪汪!");
    }
}

var dog = new Dog();
dog.move();
dog.makeSound();

运行结果:

动物在移动
汪汪汪!

综合实例

综合运用类的各种特性:

实例

// 接口定义
interface I Printable {
    print(): void;
}

// 抽象类
abstract class Item {
    protected name: string;
    protected price: number;

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

    abstract getDetails(): string;
}

// 具体类
class Product extends Item implements I Printable {
    private category: string;

    constructor(name: string, price: number, category: string) {
        super(name, price);
        this.category = category;
    }

    // 实现抽象方法
    getDetails(): string {
        return `产品: ${this.name}, 价格: ¥${this.price}, 类别: ${this.category}`;
    }

    // 实现接口方法
    print(): void {
        console.log(this.getDetails());
    }

    // 静态方法
    static create(name: string, price: number): Product {
        return new Product(name, price, "默认类别");
    }
}

// 使用
var product = Product.create("笔记本电脑", 5999);
product.print();

// 折扣方法
class DiscountedProduct extends Product {
    private discount: number;

    constructor(name: string, price: number, category: string, discount: number) {
        super(name, price, category);
        this.discount = discount;
    }

    getDetails(): string {
        var discountedPrice = this.price * (1 - this.discount / 100);
        return `产品: ${this.name}, 原价: ¥${this.price}, 折扣: ${this.discount}%, 现价: ¥${discountedPrice.toFixed(2)}`;
    }
}

var discountedProduct = new DiscountedProduct("手机", 2999, "电子产品", 20);
discountedProduct.print();

运行结果:

产品: 笔记本电脑, 价格: ¥5999, 类别: 默认类别
产品: 手机, 原价: ¥2999, 折扣: 20%, 现价: ¥2399.20

总结

TypeScript 的类提供了完整的面向对象编程支持:

  • 类的定义:使用 class 关键字,包含字段、构造函数和方法
  • 访问修饰符:public、private、protected 控制成员访问权限
  • 继承:使用 extends 实现类继承,支持多层继承
  • 方法重写:子类可以重写父类方法,使用 super 调用父类
  • 静态成员:使用 static 关键字,属于类本身而非实例
  • 接口实现:使用 implements 关键字实现接口
  • 抽象类:使用 abstract 关键字,不能实例化,作为基类

类是 TypeScript 面向对象编程的基础,合理使用类可以使代码更加结构化和可维护。