资讯专栏INFORMATION COLUMN

TypeScript 初识 - 类

邹强 / 724人阅读

摘要:抽象类抽象类做为其它字类的基类使用,一般不会直接被实例化。抽象类中可以包含具体实现,接口不能。抽象类在运行时是可见的,可以通过判断。接口只能描述类的公共部分,不会检查私有成员,而抽象类没有这样的限制。

一个普通的类
class Greeter {
    greeting: string;
    constructor(message: string) {
        this.greeting = message;
    }
    greet() {
        return "Hello, " + this.greeting;
    }
}

let greeter = new Greeter("world");
继承

super 作为函数调用时,代表父类的构造函数。子类的构造函数必须执行一次 super 函数,并且在构造函数里访问 this 的属性之前一定要调用 super()

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

super 虽然代表了父类 Animal 的构造函数,但是返回的是子类 Snake 的实例,即 super 内部的 this 指的是 Snake 的实例,因此 super() 在这里相当于 Animal.prototype.constructor.call(this)

访问修饰符 public

在 TypeScript 中,所有访问修饰符默认为 public,这个和 JavaScript 是一致的:

// 这和上面例子是一致的
class Animal {
    public name: string;
    public constructor(theName: string) {
        this.name = theName;
    }
    public move(distanceInMeters: number) {
        console.log(`${this.name} moved ${distanceInMeters}m.`);
    }
}
private

private 意为私有,使用 private 修饰的变量,不允许在类的外面使用,子类中也不允许访问:

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

new Animal("Cat").name; // Error

在 TypeScript 中,如果两个类的所有成员的类型都是兼容的,这就表示两个类是兼容的。

但是,一个类里有 privateprotected 修饰的成员,另一个类中的变量必须拥有来自同一处声明相同修饰的变量,这两个类才算是兼容的:

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 = employee; // 不能将类型“Employee”分配给类型“Animal”。类型具有私有属性“name”的多带带声明。
protected

protected 唯一比 private 修饰的成员多出的权限在于,protected 修饰的成员可以在子类中使用,但仍不允许在类的外面使用。

构造函数可以被 protected 修饰,修饰后的类无法被实例化,只能被继承。

readonly 修饰符

readonly 可以将属性设置为只读,只读属性只能在声明时或者构造函数里进行初始化:

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"; // 错误! name 是只读的
参数属性

参数属性可以方便地在一个类里定义并初始化一个成员:

// 这里和上面定义的类是一样的
class Octopus {
    readonly numberOfLegs: number = 8;
    // 把声明和赋值合并到一起
    constructor(readonly name: string) {}
}

参数属性通过给构造函数参数前面添加一个访问限定符来声明。使用 private 限定一个参数属性会声明并初始化一个私有成员;publicprotected 也是一样。

存取器

TypeScript 中的类支持取值函数(getter)、存值函数(setter):

let passCode = "secret passCode";

class Employee {
    // 私有属性
    private _fullName: string;

    // getter
    get fullName(): string {
        return this._fullName;
    }

    // setter
    set fullName(newName: string) {
        if (passCode && passCode == "secret passCode") {
            this._fullName = newName;
        } else {
            console.log("Error: Unauthorized update of employee!");
        }
    }
}

let employee = new Employee();
employee.fullName = "Bob Smith";
if (employee.fullName) {
    alert(employee.fullName);
}

存取器必须要编译器设置(compilerOptions.target)输出为 ES6 或更高。

只带有 get 不带有 set 的存取器会自动被推断为 readonly

静态属性

TypeScript 中的类支持静态成员,可以在没有实例化的情况下进行访问,使用 static 进行修饰:

class Grid {
    static origin = { x: 0, y: 0 };
    calculateDistanceFromOrigin(point: { x: number; y: number }) {
        // 类里使用静态成员需要加上类名,使用访问和 this 相同
        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) {}
}

let grid = new Grid(1.0);

console.log(grid.calculateDistanceFromOrigin({ x: 10, y: 10 }));
// 14.142135623730951
console.log(Grid.origin);
// Object {x: 0, y: 0}

静态方法调用不了实例化方法和实例化属性,因为静态域加载是在解析阶段,而实例化是在初始化阶段,所以静态方法里面不能调用本类的方法和属性,可以调用静态属性和静态方法。

抽象类

抽象类做为其它字类的基类使用,一般不会直接被实例化。不同于接口,抽象类可以包含成员的实现细节。abstract 关键字是用于定义抽象类和在抽象类内部定义抽象方法:

abstract class Animal {
    abstract makeSound(): void;
    move(): void {
        console.log("moving...");
    }
}

抽象类中的抽象方法不包含具体实现并且必须在字类中实现。抽象方法必须包含 abstract 关键字并且可以包含访问修饰符。

类和接口

类定义会创建两个东西:类的实例类型和一个构造函数。因为类可以创建出类型,所以可以在使用接口的地方使用类:

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

interface Point3d extends Point {
    z: number;
}

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

类可以实现(implement)接口。通过接口可以强制指明类遵守某个契约。也可以在接口中声明一个方法,然后要求类去具体实现它。

接口不可以被实例化,实现接口必须重写接口中的抽象方法。

类可以实现(implement)多个接口,但只能扩展(extends)自一个抽象类。

抽象类中可以包含具体实现,接口不能。

抽象类在运行时是可见的,可以通过 instanceof 判断。接口则只在编译时起作用。

接口只能描述类的公共(public)部分,不会检查私有成员,而抽象类没有这样的限制。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/106889.html

相关文章

  • TypeScript 初识 - 接口

    摘要:接口的作用是声明变量的结构和方法,但不做具体的实现。这两个使用场景不同。额外的属性检查从字面上的意思看,其实就是对接口未定义的属性进行检查。上面的例子,定义了接口,它具有索引签名。它不会帮你检查类是否具有某些私有成员。 接口的作用是声明变量的结构和方法,但不做具体的实现。通常,接口会强制对所有成员进行类型检查,包括数量和类型: interface Name { first: s...

    gnehc 评论0 收藏0
  • 那些年初识Angular(1)

    摘要:它包含多个属性,这些属性值叫做元数据。会根据元数据渲染组件,并执行组件逻辑。元数据会告诉图和将这个类处理成一个组件。元数据这段代码表示这个组件可以通过这个标签来调用。 那些年初识Angular 由于工作需要初识了Angular,由于个人在学习一门新语言的时候喜欢买一本相关的书籍自己钻研,还记得自己的第一本Angular书籍是关于Angular2的学习,自此正式踏入Angular的学习。...

    Flink_China 评论0 收藏0
  • TypeScript 初识 - 高级

    摘要:联合类型联合类型表示一个值可以时集中类型之一,使用进行分隔每种类行。联合类型的变量在被赋值的时候,根据类型推论的规则,推断出一个类型。 联合类型 联合类型表示一个值可以时集中类型之一,使用 | 进行分隔每种类行。 联合类型的变量在被赋值的时候,根据类型推论的规则,推断出一个类型。 联合类型的变量当被推断出类型后,就变得和正常声明的变量一样: let ddd: string | numb...

    CatalpaFlat 评论0 收藏0
  • TypeScript 初识

    摘要:当你陷在一个中大型项目中时应用日趋成为常态,没有类型约束类型推断,总有种牵一发而动全身的危机和束缚。总体而言,这些付出相对于代码的健壮性和可维护性,都是值得的。目前主流的都为的开发提供了良好的支持,比如和。参考资料中文文档 文章博客地址:http://pinggod.com/2016/Typescript/ TypeScript 是 JavaScript 的超集,为 JavaScrip...

    iliyaku 评论0 收藏0
  • TypeScript 初识 - 内置对象

    摘要:自带的内置对象都可以直接在中当作定义好的类型。的内置对象标准提供了常用的内置对象等。在不需要额外引入就可以直接使用这些内置对象用写不是内置对象的一部分,想要写时提示,需要引入第三方声明文件 JavaScript 自带的内置对象都可以直接在 TypeScript 中当作定义好的类型。 TypeScript 核心库的定义文件 TypeScript 核心库的定义文件定义了所有浏览器环境需要用...

    lordharrd 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<