# 类

## 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}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://yes-1-am.gitbook.io/blog/typescript-yu-fa/lei.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
