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(); // 正确...
复制代码

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

 
 
 
posted @   He_LiangLiang  阅读(5346)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示