Skip to content

TypeScript 类和对象

类(Class)是面向对象编程(OOP)的核心概念,它是创建对象的蓝图。TypeScript 全面支持 ES6 中引入的类语法,并在此基础上添加了类型注解、访问修饰符等特性。

什么是类和对象?

  • 类 (Class): 一个模板或蓝图,用于描述一类对象的共同属性(数据)和行为(方法)。
  • 对象 (Object): 类的一个实例。通过 new 关键字创建,拥有类所定义的属性和方法。

定义一个类

下面是一个简单的类定义:

typescript
class Greeter {
    // 属性 (Property)
    greeting: string;

    // 构造函数 (Constructor)
    constructor(message: string) {
        this.greeting = message;
    }

    // 方法 (Method)
    greet() {
        return "Hello, " + this.greeting;
    }
}

// 创建类的实例(一个对象)
let greeter = new Greeter("world");

console.log(greeter.greet()); // "Hello, world"

继承 (Inheritance)

继承是允许一个类(子类)获取另一个类(父类)的属性和方法的一种机制。使用 extends 关键字来实现继承。

typescript
class Animal {
    name: string;
    constructor(theName: string) { this.name = theName; }
    move(distanceInMeters: number = 0) {
        console.log(`${this.name} moved ${distanceInMeters}m.`);
    }
}

// Snake 是 Animal 的子类
class Snake extends Animal {
    constructor(name: string) {
        super(name); // 调用父类的构造函数
    }
    move(distanceInMeters = 5) {
        console.log("Slithering...");
        super.move(distanceInMeters); // 调用父类的方法
    }
}

let sam = new Snake("Sammy the Python");
sam.move();
// Slithering...
// Sammy the Python moved 5m.
  • super(): 在子类的构造函数中,必须调用 super() 来执行父类的构造函数。
  • super.method(): 可以用来调用父类中被重写(override)的方法。

访问修饰符 (Access Modifiers)

TypeScript 提供了三种访问修饰符,用于控制类成员(属性和方法)的可访问性。

  • public (默认): 成员可以在任何地方被访问。如果你不指定修饰符,它默认为 public

  • private: 成员只能在声明它的类内部被访问。子类和类的实例都无法访问。

    typescript
    class Person {
        private name: string;
        constructor(name: string) { this.name = name; }
        public greet() {
            console.log(`Hello, my name is ${this.name}`);
        }
    }
    
    let john = new Person("John");
    john.greet(); // OK
    // console.log(john.name); // Error: Property 'name' is private.
  • protected: 成员可以在声明它的类以及该类的子类中被访问,但不能在类的实例上访问。

    typescript
    class Employee extends Person {
        private department: string;
        constructor(name: string, department: string) {
            super(name);
            this.department = department;
        }
        public getElevatorPitch() {
            // 可以在子类中访问父类的 protected 成员
            // return `Hello, my name is ${this.name} and I work in ${this.department}.`;
            // 如果 name 是 protected,上面这行是 OK 的。如果是 private,则会报错。
        }
    }

只读修饰符 (readonly)

readonly 关键字可以确保属性在声明时或构造函数中被初始化后,不能再被修改。

typescript
class Octopus {
    readonly name: string;
    readonly numberOfLegs: number = 8;
    constructor(theName: string) {
        this.name = theName;
    }
}

let dad = new Octopus("Man with the 8 strong legs");
// dad.name = "Man with the 3-piece suit"; // Error! name is readonly.

静态属性和方法 (static)

静态成员属于类本身,而不是类的实例。你可以直接通过类名来访问它们,而不需要创建对象。

typescript
class Grid {
    static origin = { x: 0, y: 0 };
    calculateDistanceFromOrigin(point: { x: number; y: number; }) {
        let xDist = (point.x - Grid.origin.x);
        let yDist = (point.y - Grid.origin.y);
        return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;
    }
    constructor(public scale: number) { }
}

console.log(Grid.origin); // { x: 0, y: 0 }
let grid1 = new Grid(1.0);

抽象类 (abstract)

抽象类是作为其他类的基类的。它们不能被直接实例化。抽象类中可以包含抽象方法,这些方法没有具体的实现,必须在派生类中被实现。

typescript
abstract class Department {
    constructor(public name: string) {}

    printName(): void {
        console.log("Department name: " + this.name);
    }

    abstract printMeeting(): void; // 必须在派生类中实现
}

class AccountingDepartment extends Department {
    constructor() {
        super("Accounting and Auditing");
    }

    printMeeting(): void {
        console.log("The Accounting Department meets each Monday at 10am.");
    }
}

let department: Department; // 允许创建一个对抽象类型的引用
// department = new Department(); // 错误: 不能创建一个抽象类的实例
department = new AccountingDepartment(); // 允许对一个抽象子类进行实例化和赋值
department.printName();
department.printMeeting();

本站内容仅供学习和研究使用。