Typescript子类函数重载 [英] Typescript child class function overloading

查看:119
本文介绍了Typescript子类函数重载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在打字稿中实现类似于此模式的功能?

How can I achieve something similar to this pattern in typescript?

class A {
    Init(param1: number) {
        // some code
    }
}

class B extends A {
    Init(param1: number, param2: string) {
        // some more code
    }
}

上面截断的代码似乎应该工作,但是仔细检查 Typescript函数重载的工作方式抛出错误是有道理的:

The code snipped above appears like it should work, however on close inspection of How Typescript function overloading works it makes sense that an error is thrown:

TS2415: 'Class 'B' incorrectly extends base class 'A'. 
Types of property 'Init' are incompatible.

我知道构造函数允许这种行为,但是我不能在这里使用构造函数,因为这些对象被池化以提高内存效率.

I know that constructor functions allow this behaviour, but I can't use constructors here as these objects are pooled for memory efficiency.

我可以在A类中提供Init()的另一种定义:

I could provide another definition of Init() in class A:

class A {
    Init(param1: number, param2: string): void;
    Init(param1: number) {
        // some code
    }
}

但是,这并不理想,因为现在基类需要了解其所有派生类.

However this is less than ideal as now the base class needs to know about all of its derived classes.

第三个选择是重命名类B中的Init方法,但这不仅很丑陋和令人困惑,而且在基类中暴露了Init()方法,这将在以下情况下导致难以检测的错误:基类Init()被错误地调用.

A third option would be to rename the Init method in class B but that would not only be pretty ugly and confusing, but leave exposed the Init() method in the base class, which would cause difficult-to-detect bugs when the base class Init() is called by mistake.

有没有办法实现这种模式,而没有前面提到的方法的陷阱?

Is there any way to implement this pattern that doesn't have the pitfalls of the aforementioned approaches?

推荐答案

TypeScript抱怨方法不可互换:如果执行以下操作会发生什么?

TypeScript complains about methods not being interchangeable: what would happen if you do the following?

let a:A = new A(); // a is of type A
a.Init(1)
a = new B(); // a is still of type A, even if it contains B inside
a.Init(1) // second parameter is missing for B, but totally valid for A, will it explode?

如果您不需要它们可互换,请修改B的签名以符合A的签名:

If you don't need them to be interchangeable, modify B's signature to comply with A's:

class B extends A {
    Init(param1: number, param2?: string) { // param 2 is optional
        // some more code
    }
}

但是,您可能会发现自己需要创建一个具有完全不同的方法签名的类:

However, you might find yourself in a situation where you need to create a class with totally different method signature:

class C extends A {
    Init(param1: string) { // param 1 is now string instead of number
        // some more code
    }
}

在这种情况下,添加同时满足当前类和基类调用的方法签名的列表.

In this case, add a list of method signatures that satisfy both current class and base class calls.

class C extends A {
    Init(param1: number)
    Init(param1: string)
    Init(param1: number | string) { // param 1 is now of type number | string (you can also use <any>)
        if (typeof param1 === "string") { // param 1 is now guaranteed to be string
            // some more code
        }
    }
}

这样,A类不必知道任何派生类.作为一种折衷,您需要指定一个同时满足基类和子类方法调用的签名列表.

That way the A class doesn't have to know about any of the derived classes. As a trade-off, you need to specify a list of signatures that satisfies both base class and sub class method calls.

这篇关于Typescript子类函数重载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆