打字稿抽象方法重载

时间:2017-05-15 13:45:24

标签: oop typescript abstract

我想在抽象类中重载一个抽象方法,如下所示:

abstract class Animal {

    public abstract communicate(sentence: string): void;
    public abstract communicate(notes: string[]): void;

}

class Human extends Animal {

    public communicate(sentence: string): void {
        // Do stuff
    }

}

class Bird extends Animal {

    public communicate(notes: string[]): void {
        // Do stuff
    }

}

但是,Typescript会出错,说明我错误地扩展了基类(Animal)

我做错了吗?就像期待一些工作,根据OOP无论如何都可以工作?还是打字稿不支持?

注意:与此示例不同,参数的类型可以是完全不同的类型。

3 个答案:

答案 0 :(得分:2)

该抽象类需要实现两个方法签名。这两个方法签名是:

public abstract communicate(sentence: string): void;
public abstract communicate(notes: string[]): void;

它们可以这样实现:

class Human extends Animal {
    communicate(sentence: string); // optional overload signature
    communicate(notes: string[]);  // optional overload signature
    communicate(sentenceOrNotes: string | string[]) {
        // Do stuff
    }
}

最终的签名是实施签名。它需要与需要实现的方法签名兼容。

关于子类的注意事项

子类需要与基础兼容,以便在您执行时...

const animal: Animal = new Bird();

...子类应该能够处理两个调用:

animal.communicate("some sentence");
animal.communicate(["notes", "more notes"]);

在这种情况下,根据通信形式(或使用mixins)创建单独的接口可能更合适:

interface CommunicatesWithSentences {
    communicate(sentence: string);
}

class Human extends Animal implements CommunicatesWithSentences {
    communicate(sentence: string) {
        // Do stuff
    }
}

答案 1 :(得分:2)

与@DavidSherret一样,子类必须实现所有抽象类重载,而不仅仅是其中之一。因此,您无法使用抽象类重载来实现您想要的功能。

由于你想要的是BirdHuman具有不同的communicate() param类型,由编译器强制执行,我将使用类型约束的泛型类型参数:

abstract class Animal<C extends string | string[]> {
    public abstract communicate(communication: C): void;
}

class Human extends Animal<string> {
    public communicate(sentence: string): void { }
}

class Bird extends Animal<string[]> {
    public communicate(notes: string[]): void { }
}

class Bynar extends Animal<boolean> { // Error: 'boolean' does not satisfy the constraint 'string | string[]'.
    public communicate(bit: boolean): void { }
}

const human = new Human();
human.communicate("hello"); // OK
human.communicate(["hello"]); // Error

const bird = new Bird();
bird.communicate("hello"); // Error
bird.communicate(["hello"]); // OK

提示:您也可以在此处使用TS 2.3 default type arguments

答案 2 :(得分:0)

您可以这样做,希望对您有用。

export abstract class BaseComponent {

     constructor(protected valueName: string) {

     }

     protected doSomethingMoreButOptional(config: IConfig): void { }

     protected doSomething() {
         if (valueName === 'derived') {
             this.doSomethingMoreButOptional(new Config());
         }
     }
}

export class DerivedComponent extends BaseComponent {

    private _xxx: any[];
    private _yyy: any[];

    constructor() {
        super('derived');
        super.doSomething();
    }

    protected doSomethingMoreButOptional(config: IConfig): void {
        switch (config.ABC) {
           case 'xxx':
              config.options = this._xxx;
              break;

           case 'yyy':
              config.options = this._yyy;
              break;

           default:
              return;
        }
    }
}