Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Inheritance Typescript子类函数重载_Inheritance_Typescript_Overloading - Fatal编程技术网

Inheritance Typescript子类函数重载

Inheritance Typescript子类函数重载,inheritance,typescript,overloading,Inheritance,Typescript,Overloading,如何在typescript中实现类似于此模式的功能 class A { Init(param1: number) { // some code } } class B extends A { Init(param1: number, param2: string) { // some more code } } 上面截取的代码看起来应该可以正常工作,但是仔细检查后发现抛出了一个错误: TS2415: 'Class 'B' inc

如何在typescript中实现类似于此模式的功能

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

class B extends A {
    Init(param1: number, param2: string) {
        // some more code
    }
}
上面截取的代码看起来应该可以正常工作,但是仔细检查后发现抛出了一个错误:

TS2415: 'Class 'B' incorrectly extends base class 'A'. 
Types of property 'Init' are incompatible.
我知道构造函数允许这种行为,但我不能在这里使用构造函数,因为这些对象是为了提高内存效率而合并的

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

class A {
    Init(param1: number, param2: string): void;
    Init(param1: number) {
        // some code
    }
}
但是,这并不理想,因为现在基类需要了解其所有派生类

第三种选择是重命名类B中的Init方法,但这不仅非常难看和混乱,而且会在基类中暴露Init()方法,这将导致在错误调用基类Init()时难以检测错误


有没有任何方法可以实现这种模式而不存在上述方法的缺陷?

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

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
的要求:

class B extends A {
    Init(param1: number, param2?: string) { // param 2 is optional
        // some more code
    }
}
但是,您可能会发现自己需要创建一个具有完全不同的方法签名的类:

class C extends A {
    Init(param1: string) { // param 1 is now string instead of number
        // some more code
    }
}
在本例中,添加同时满足当前类和基类调用的方法签名列表

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
        }
    }
}
C类扩展了{
初始化(参数1:编号)
Init(param1:string)
Init(param1:number | string){//param1现在是number | string类型(您也可以使用)
如果(typeof param1==“string”){//param 1现在保证为string
//还有代码吗
}
}
}

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

对于想要扩展类型的人。 基于、使用


谢谢你的回复!如果可以避免的话,我不想做运行时类型检查,但是Typescript在其他地方都能做到这一点。不幸的是,如果你的子类的方法签名与基类的签名不匹配,你就不能不做运行时检查。看看我的第一个例子:可能有人在调用你的子类,好像它实际上是base claseAh,好吧,我想我现在明白了。也许我会让这两个类从抽象基类继承它们的其他公共属性。
a.Init(1)
应该最终调用a的Init方法,因为OOP就是这样工作的。具有1个参数的Init签名由A继承,具有2个参数的Init签名从B继承。
interface ConsumerGroup {
  on(message: 'message'): void
  on(message: 'error'): void
}

interface ConsumerGroup2 {
  on(message: 'messageDecoded'): void;
  on(message: 'rawMessage'): void;
}

// Intersection types
type ConsumerGroupEx = ConsumerGroup2 & ConsumerGroup;

function newEvent(): ConsumerGroupEx {
  return "just for test" as unknown as ConsumerGroupEx;
}

const evt = newEvent();

evt.on('messageDecoded'); // ok
evt.on('message'); // ok
evt.on('error'); // ok
evt.on('notExist'); // compilation error