打字稿:访问祖父母类方法

时间:2019-03-07 10:51:22

标签: typescript

我有一个三班制的家庭:

abstract class Form {
    protected async submit({ url: string, data: any }): Promise<void> {
        // submit data from form
    }
}

abstract class BookForm extends Form {
    public name?: string;

    public abstract async submit(): Promise<void>
}

class UpdateBookForm extends BookForm {
    private id: string;

    public async submit(): Promise<void> {
        // Abstract method 'submit' in class 'BookForm' cannot be accessed via super expression.
        return super.submit({
            url: '/book/update',
            data: {
                id: this.id,
                name: this.name,
            }
        });
    }

    constructor(bookId: string) {
        super()
        this.id = bookId;
    }
}

尝试从super.submit()访问UpdateBookForm方法时遇到错误。

  

无法通过超级表达式访问“ BookForm”类中的抽象方法“ submit”。

我要实现的目标是BookForm知道其包含方法submit()的派生类,而在BookForm中没有任何实现。

关于如何实现此目标的任何建议?也许我可以直接从super.super访问祖父母(UpdateBookForm?)?

3 个答案:

答案 0 :(得分:2)

abstract删除BookForm方法,使其:

abstract class BookForm extends Form {
    public name?: string;
}

仅仅制作BookForm abstract就足以防止它被使用。

您永远不想用不存在的方法(在Form中覆盖现有的方法(在BookForm中)。

在评论中,您概述了制作submit abstract的动机,方法是(我在下面将“ save”更改为“ submit”,匹配问题):

  

好吧,好吧,我在BookForm中有一个const bookForm = this.book ? new UpdateBookForm(this.book) : new CreateBookForm()的实例,我尝试保存它bookForm.submit(),它期望从submit使用Form方法需要参数。我想打bookForm.submit()

如果BookFormUpdateBookForm没有有意义的submit接受参数,则它们违反了子类实例“是”超类实例的规则,因为它们不是Form个。有多种解决方法。一种方法是制作submit protected并让BookForm添加abstract save之类的东西。然后UpdateBookFormCreateBookForm将通过调用save来实现submit

但是我还要仔细检查继承在这里是否正确。没有更多的上下文很难说。


旁注:BookForm应该有一个初始化name的构造函数。引入字段而无需在层次结构的相同级别上对其进行初始化的方法似乎是不可能的。

答案 1 :(得分:0)

尽管您可能会考虑重新设计代码,但是您可以直接使用祖父母类名称来调用它。

abstract class Form {
    async submit({ url: string, data: any }): Promise<void> {
        // submit data from form
    }
}

abstract class BookForm extends Form {
    public name?: string;

    abstract async submit(): Promise<void>
}

class UpdateBookForm extends BookForm {
    private id: string;

    async submit(): Promise<void> {
        return Form.prototype.submit.call(this, {
            url: '/book/update',
            data: {
                id: this.id,
                name: this.name,
            }
        });
    }
}

答案 2 :(得分:0)

感谢T.J.根据Crowder的回答,我得出的结论是Form submit({ url: string, data: any })函数实际上与子类submit()函数完全不同,因此将它们分成两个这样的函数是有意义的:

abstract class Form {
    protected async submit({ url: string, data: any }): Promise<void> {
        // submit data from form
    }
    public abstract async save(): Promise<void>
}

abstract class BookForm extends Form {
    public name?: string;

    public abstract async save(): Promise<void>
}

class UpdateBookForm extends BookForm {
    private id: string;

    public async save(): Promise<void> {
        return super.submit({
            url: '/book/update',
            data: {
                id: this.id,
                name: this.name,
            }
        });
    }

    constructor(bookId: string) {
        super()
        this.id = bookId;
    }
}