> For the complete documentation index, see [llms.txt](https://yes-1-am.gitbook.io/blog/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://yes-1-am.gitbook.io/blog/typescript-yu-fa/lei.md).

# 类

## 1. 继承

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

class Snake extends Animal {
    constructor(name: string) { super(name); }      // super
    move(distanceInMeters = 5) {
        console.log("Slithering...");
        super.move(distanceInMeters);
    }
}

class Horse extends Animal {
    constructor(name: string) { super(name); }
    move(distanceInMeters = 45) {
        console.log("Galloping...");
        super.move(distanceInMeters);
    }
}
```

如果子类包含了构造函数，那么它必须调用 super(), 它会执行基类的构造函数。并且在构造函数访问this属性之前，一定要调用 super();

## 2. 公共，私有与受保护的修饰符

在 typescript 里，成员都默认为 public

```
class Animal {
    public name: string;
    public constructor(theName: string) {
        this.name = theName;
    }
    public move(distabceInMeters: number) {
        ...
    }
}
```

**private**

```
class Animal {
    private name: string;
    constructor(theName: string) {
        this.name = theName;
    }
}

new Animal('CAT').name;      // error, 不能再声明它的类之外访问
```

**protected**

protected 与 privated 类似，但是 protected 成员在子类中可以访问。

```
class Person {
    protected name: string;
    constructor(name: string) { this.name = name; }
}

class Employee extends Person {
    private department: string;

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

    public getElevatorPitch() {
        return `Hello, my name is ${this.name} and I work in ${this.department}.`;
    }
}

let howard = new Employee("Howard", "Sales");
console.log(howard.getElevatorPitch());  // 成功，在子类中访问属性
console.log(howard.name); // 错误，不能在子类之外访问
```

## 3. 静态属性

```
class Grid {
    static origin = {
        x: 0,
        y: 0
    }
    calculate(point: { x: number, y: number } ) {
        let xDist = point.x - Grid.origin.x;      // 静态属性的使用，直接用类.属性名
    }
}
```

## 4. 抽象类

抽象类作为其它派生类的基类使用，不会直接被实例化。

使用 abstract 关键字定义抽象类和在抽象类内部定义抽象方法

```
abstract class Animal {
    abstract makeSound(): void;   // 抽象方法，必须在派生类中实现
    move(): void {

    }
}
```

## 5. 构造函数

在TypeScript中声明一个类的时候，实际上声明了很多东西，比如， **类的实例的类型**

```
class Greeter {
    greeting: string;
    constructor(message: string) {
        this.greeting = message;
    }
}

let greeter: Greeter;     // 表明 greeter 是 Greeter 类的实例的类型
```

除了类的实例的类型，我们可能还关注，*类的类型*

```
class Greeter {
    static standardGreeting = "Hello, there";
    greeting: string;
    greet() {
        if (this.greeting) {
            return "Hello, " + this.greeting;
        }
        else {
            return Greeter.standardGreeting;
        }
    }
}

let greeter1: Greeter;
greeter1 = new Greeter();
console.log(greeter1.greet());

// 得到 Gretter 的类的类型，这时候声明的变量，和 Gretter一样，可以被 new 
let greeterMaker: typeof Greeter = Greeter;
greeterMaker.standardGreeting = "Hey there!";

let greeter2: Greeter = new greeterMaker();
console.log(greeter2.greet());
```

即通过 `typeof` 操作符，可以得到类的类型。

## 5. 把类当接口使用

类定义会创建两个东西： 类的实例类型和一个构造函数，那么实例类型就可以当做接口去使用

```
class Point {
    x: number;
    y: number;
}

interface Point3d extends Point {  // 当做接口去继承
    z: number;
}

let point3d: Point3d = {x:1, y:2, z:3}
```
