3
class MySystem extends ListIteratingSystem {
    constructor (private creator: EntityCreator) {
        super(MyNode, this.updateNode);
    }

    updateNode() {/* sniiiiip */}

    /* sniiiip */
}

在上面的代码中,我需要某种方式将 updateNode 函数传递给 super 调用。编译器对此抱怨说:

Keyword 'this' cannot be referenced in initializers in a class body, or in super constructor calls

关于如何解决这个问题的任何想法?这里的用例是我已经将大量与列表遍历等相关的样板代码抽象到这个基类中,该基类由几个执行实际工作的特定系统扩展。基类需要调用更新、添加和删除的方法...

4

3 回答 3

5

我不是 100% 清楚您的用例的语义,但您可以根据目标选择一些选项。

首先是将updateNode//定义为addNoderemoveNode类的成员,并让派生类覆盖它们(而不是将它们指定为构造函数参数)。这对于您的派生实现来说不太清楚,因为 TypeScript 没有“抽象”的概念,但可能是最干净和最简单的。

第二个是重构一点,让派生类提供一个类型参数而不是方法列表,并将更新/添加/删除函数放在“姐妹”类中,以让基类提供该功能的方式它们是您本来可以从中获得的所需上下文this。这是更多的工作,但更好地分离了关注点。如果您正在尝试实现控制模式的反转,那么通过组合而不是继承可能会更好。

最后一个选项是将此处的整个类层次结构颠倒过来,并将遍历/等代码移动到这些单独的实现将使用的单独类中,从本质上消除现有代码中的任何控制反转。

我应该补充一点,您未this在基类构造函数参数位置中引用的限制通常是一个非常好的限制 - 试图违反它通常意味着您将自己设置为进一步失败。MySystem在这种情况下,如果没有适当的限制,当您尝试从 继承时,或者当ListIteratingSystem决定它应该updateNode在构建期间的某个时间调用时,您可能会遇到大麻烦。出于同样的原因,C# 中的 FxCop 强制执行此限制。

于 2012-11-30T06:56:19.877 回答
3

从 TypeScript 1.3 开始,您可以使用 protected 关键字和后期绑定,因此您不必将方法传递给超类。

仍然没有abstract关键字,因此您必须提供默认行为或在基类中引发异常 - 但protected关键字允许您覆盖基类实现(在当前版本的 TypeScript 中,private 关键字不允许这样做) .

class ListIteratingSystem {
    doSomething() {
        this.updateNode();
    }

    protected updateNode() {
        alert('Super');
    }
}

class MySystem extends ListIteratingSystem {
    protected updateNode() {
        alert('Sub');
    }
}

var a = new ListIteratingSystem();
a.doSomething();

var b = new MySystem();
b.doSomething();
于 2014-11-17T08:05:46.847 回答
3

你为什么不重写这样的方法:

class ListIteratingSystem {
    execute() {
        this.executeOnStart();
    };

    private executeOnStart() {
       throw new Error('This method is abstract');
    };
};

class MySystem extends ListIteratingSystem {
    constructor (/*...*/) {
        super();
    }

   private executeOnStart() {
       alert("derived");
    };
}

执行new MySystem().execute();显示警报。

不幸的是,还没有很好的方法来制作executeOnStart方法protected abstract。这有点违反直觉,但请记住可见性访问器仅用于编译器和智能。

于 2012-11-30T06:52:26.320 回答