首页 文章

打字稿抽象方法重载

提问于
浏览
2

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

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无论如何都可以工作?或者这是Typescript不支持的东西?

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

2 回答

  • 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

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

    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
        }
    }
    

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

    Note on Child Classes

    子类需要与基础兼容,这样当你做...

    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
        }
    }
    

相关问题