ts从入门到进阶—4.2类
发布日期:2021-05-06 19:34:52 浏览次数:14 分类:精选文章

本文共 3755 字,大约阅读时间需要 12 分钟。

6.静态属性

  • 类的实例成员。仅当类被实例化的时候才会被初始化的属性。使用this前缀访问
  • 类的静态成员。存在于类本身上面而不是类的实例上。使用类名(Grid)前缀访问,(不管是在类的里面还是外面都是这样访问)
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) { }}let grid1 = new Grid(1.0);  // 1x scalelet grid2 = new Grid(5.0);  // 5x scaleconsole.log(grid1.calculateDistanceFromOrigin({x: 10, y: 10}));console.log(grid2.calculateDistanceFromOrigin({x: 10, y: 10}));

7.抽象类

  • 用途:抽象类作为其他派生类的基类使用,也就是说一般充当父类
  • 特点:1⃣️一般不会直接被实例化。2⃣️抽象类的非抽象方法可以包括成员细节,抽象方法不能包括具体实现并且必须在派生类中实现(所谓成员细节就是方法内部是怎么实现的)3⃣️如何辨别抽象类和抽象方法,在前面加abstract关键字。
abstract class Animal {    abstract makeSound(): void;    move(): void {        console.log('roaming the earch...');    }}

重点说一下抽象类的抽象方法

  • 抽象类中的抽象方法不包含具体实现并且必须在派生类中实现。
  • 抽象方法的语法与接口方法相似。 两者都是定义方法签名但不包含方法体。 
  • 抽象方法必须包含 abstract关键字并且可以包含访问修饰符。
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'); // 在派生类的构造函数中必须调用 super()    }    printMeeting(): void {        console.log('The Accounting Department meets each Monday at 10am.');    }    generateReports(): void {        console.log('Generating accounting reports...');    }}let department: Department; // 允许创建一个对抽象类型的引用// department = new Department(); // 错误: 不能创建一个抽象类的实例department = new AccountingDepartment(); // 允许对一个抽象子类进行实例化和赋值department.printName();department.printMeeting();department.generateReports(); // 错误: 方法在声明的抽象类中不存在,注意此处报错是因为一开始声明let department: Department; 。并不是说抽象类的子类不能有自己的方法

打印结果

8.高级技巧

构造函数

当你在TypeScript里声明了一个类的时候,实际上同时声明了很多东西。 首先就是类的 实例的类型。

class Greeter {    greeting: string;    constructor(message: string) {        this.greeting = message;    }    greet() {        return "Hello, " + this.greeting;    }}let greeter: Greeter;greeter = new Greeter("world");console.log(greeter.greet());

这里,我们写了 let greeter: Greeter,意思是 Greeter类的实例的类型是 Greeter。 这对于用过其它面向对象语言的程序员来讲已经是老习惯了。

我们也创建了一个叫做 构造函数的值。 这个函数会在我们使用 new创建类实例的时候被调用。 下面我们来看看,上面的代码被编译成JavaScript后是什么样子的:

let Greeter = (function () {    function Greeter(message) {        this.greeting = message;    }    Greeter.prototype.greet = function () {        return "Hello, " + this.greeting;    };    return Greeter;})();let greeter;greeter = new Greeter("world");console.log(greeter.greet());

上面的代码里, let Greeter将被赋值为构造函数。 当我们调用 new并执行了这个函数后,便会得到一个类的实例。 这个构造函数也包含了类的所有静态属性。 换个角度说,我们可以认为类具有 实例部分与 静态部分这两个部分。

让我们稍微改写一下这个例子,看看它们之间的区别:

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());let greeterMaker: typeof Greeter = Greeter;greeterMaker.standardGreeting = "Hey there!";let greeter2: Greeter = new greeterMaker();console.log(greeter2.greet());

这个例子里, greeter1与之前看到的一样。 我们实例化 Greeter类,并使用这个对象。 与我们之前看到的一样。

再之后,我们直接使用类。 我们创建了一个叫做 greeterMaker的变量。 这个变量保存了这个类或者说保存了类构造函数。 然后我们使用 typeof Greeter,意思是取Greeter类的类型,而不是实例的类型。 或者更确切的说,"告诉我 Greeter标识符的类型",也就是构造函数的类型。 这个类型包含了类的所有静态成员和构造函数。 之后,就和前面一样,我们在 greeterMaker上使用 new,创建 Greeter的实例。

把类当做接口使用

如上一节里所讲的,类定义会创建两个东西:类的实例类型和一个构造函数。 因为类可以创建出类型,所以你能够在允许使用接口的地方使用类。

class Point {    x: number;    y: number;}interface Point3d extends Point {    z: number;}let point3d: Point3d = {x: 1, y: 2, z: 3};

 

上一篇:前端技巧和工具—excel表格数据转json
下一篇:ts从入门到进阶—4.1类

发表评论

最新留言

不错!
[***.144.177.141]2025年04月06日 06时51分13秒