typescript的高级特性(一)

一、类

先看一下例子:

class Greeter {
    greeting: string;
    constructor(message: string) {
        this.greeting = message;
    }
    greet() {
        return "Hello, " + this.greeting;
    }
}

let greeter = new Greeter("world");

我们看上面的例子中,我们声明了一个Greeter类。这里面有3个成员:一个叫greeting的属性,一个构造函数和一个greet方法。
我们在引用任何一个类成员的时候都用了this。它表示我们访问的是类的成员。
我们使用new构造了Greeter类实例,它会调用之前定义的构造函数,创建一个 Greeter类型的新对象,并执行构造函数初始化它。

二、继承

关键词:extends

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

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

const dog = new Dog();
dog.bark();
dog.move(10);
dog.bark();

类从基类中继承了属性和方法。 这里, Dog是一个 派生类,它派生自 Animal 基类,通过 extends关键字。 派生类通常被称作 子类,基类通常被称作 超类。

因为 Dog继承了 Animal的功能,因此我们可以创建一个 Dog的实例,它能够 bark()和 move()。
在上面的基础上,我们可以做一个更复杂的例子:

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); }
    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);
    }
}

let sam = new Snake("Sammy the Python");
let tom: Animal = new Horse("Tommy the Palomino");

sam.move();
tom.move(34);

与前一个例子的不同点是,派生类包含了一个构造函数,它 必须调用 super(),它会执行基类的构造函数。 而且,在构造函数里访问 this的属性之前,我们 一定要调用 super()。 这个是TypeScript强制执行的一条重要规则。
在子类中,重写了从父类中继承的move方法,使得move方法根据不同的类而具有不同的功能。

三、公共,私有与保护的修饰符

1、种类
成员的修饰符有三种:public(默认)privateprotected

当成员被标记成private时,它就不能在声明它的类的外部访问

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

new Animal("Cat").name; // 错误: 'name' 是私有的.

2、
TypeScript使用的是结构性类型系统。 当我们比较两种不同的类型时,并不在乎它们从何处而来,如果所有成员的类型都是兼容的,我们就认为它们的类型是兼容的

然而,当我们比较带有 private或 protected成员的类型的时候,情况就不同了。 如果其中一个类型里包含一个 private成员,那么只有当另外一个类型中也存在这样一个 private成员, 并且它们都是来自同一处声明时,我们才认为这两个类型是兼容的。 对于 protected成员也使用这个规则。
下面我们可以看一个例子:

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

class Rhino extends Animal {
    constructor() { super("Rhino"); }
}

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

let animal = new Animal("Goat");
let rhino = new Rhino();
let employee = new Employee("Bob");

animal = rhino;//Animal和 Rhino共享了来自 Animal里的私有成员,所以是兼容的
animal = employee; // 错误: Animal 与 Employee 不兼容.

3、protected
protected与private很相似,但是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); // 错误

不能在 Person类外使用 name,但是我们仍然可以通过 Employee类的实例方法访问,因为 Employee是由 Person派生而来的。

你可能感兴趣的:(前端)