zoukankan      html  css  js  c++  java
  • TypeScript定义一个类,以及类继承,以及虚函数,抽象基类

    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);
        }
        print()
        {
            console.log("Horse:say hello");
        }
    }
    
    let sam = new Snake("Sammy the Python");
    let tom: Animal = new Horse("Tommy the Palomino");
    
    sam.move();
    tom.move(34);
    tom.print();///vscode 编译器在语法上会报错,但是执行程序,仍然会输出 "Horse:say hello" 不太明白为啥。

    tom是Animal类型,该类型里面没有 print 方法,应该当错误处理。虽然在js下面可以正确输出,但是还是不建议这么用。

    我们可以对比C++虚函数和多态的用法来理解这里。。。在TypeScript里面,类里面的方法,默认都是 public, virtual 的。

    请参考这篇文章来理解虚函数和多态。https://www.cnblogs.com/music-liang/p/12726786.html

    请特别注意,声明的类型,和new的时候的类型。。。

    声明的时候是什么类型,它就是什么类型的。所以,tom.print() 会被编译器报错。

    关于tom.move(),而TypeScript里面默认的函数都是虚函数。因为由于virtual的存在,所以,声明的类型是父类类型(Animal),new的是子类类型(Horse),子类的虚函数覆盖了父类的虚函数(多态特性)。。

    所以,tom.move() 会调用  Horse类的move方法。。

    1.必须有构造函数 constructor 

    2.必须在构造函数里面,给属性赋值。这里有用到 this 关键字

    3.继承函数,必须在构造函数里面调用  super()函数,让父类的构造函数先执行。。。蛋疼啊。。


    这里派生类包含了一个构造函数,它 必须调用 super(),它会执行基类的构造函数。 而且,在构造函数里访问 this的属性之前,我们 一定要调用 super()。 这个是TypeScript强制执行的一条重要规则。

    这个例子演示了如何在子类里可以重写父类的方法。
    Snake类和 Horse类都创建了 move方法,它们重写了从 Animal继承来的 move方法,使得 move方法根据不同的类而具有不同的功能。 注意,即使 tom被声明为 Animal类型,但因为它的值是 Horse,调用 tom.move(34)时,它会调用 Horse里重写的方法




     
    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(); // 错误,这个是Department类型的。。。
    
    
    let department2 = new AccountingDepartment(); // 允许对一个抽象子类进行实例化和赋值
    department2.printName();
    department2.printMeeting();
    department2.generateReports(); // 正确...

    抽象基类的继承,和普通类的继承有点不一样。。

     
     
     
  • 相关阅读:
    数据同步
    闭包的内存泄漏解决办法
    No module named 'MySQLdb'
    pqi 更换pip 国内源
    BZOJ 1934 [Shoi2007]Vote 善意的投票
    BZOJ 2038 [2009国家集训队]小Z的袜子(hose)
    BZOJ 1002 [FJOI2007]轮状病毒
    BZOJ 3442 学习小组
    BZOJ 3261 最大异或和
    BZOJ 4029 [HEOI2015]定价
  • 原文地址:https://www.cnblogs.com/music-liang/p/12726558.html
Copyright © 2011-2022 走看看