当前位置: 首页 > 知识库问答 >
问题:

有没有在typescript中用mixin模拟super?

申屠乐池
2023-03-14

我通过Mixins使用多重继承(使用替代模式)。有没有办法用这个模式得到类似于“超级”的东西?考虑这里的例子

abstract class Activatable{
    private activated: boolean = false;
    constructor(){}
    public activate(): void {
        this.activated = true;
        console.log('Activatable activated')
  }
}

class SomethingElse{};

interface ThingParent extends Activatable{}

class ThingParent extends SomethingElse{
    public activate(): void {
        (this as Activatable).activate();
        let addSomeValueHere = true;
        console.log('Thing parent activated')
    }
}

applyMixins(ThingParent, [Activatable]);

class Thing extends ThingParent {
    constructor(){
        super()
    }
    public activate(): void {
        super.activate();
        
        console.log('Thing activated');
    }
}

let thing = new Thing();
thing.activate();



function applyMixins(derivedCtor: any, constructors: any[]) {
  constructors.forEach((baseCtor) => {
    Object.getOwnPropertyNames(baseCtor.prototype).forEach((name) => {
      Object.defineProperty(
        derivedCtor.prototype,
        name,
        Object.getOwnPropertyDescriptor(baseCtor.prototype, name) ||
          Object.create(null)
      );
    });
  });
}

Thing扩展了ThingP,它通过混合扩展了一个名为Activable的类。当我在Thing上调用激活时,我也想在ThingP的和Activable上调用激活,但它只在Activable上调用。

如果我更改了ThingParent上函数的名称,我可以直接调用该函数,但ThingParents不能通过super访问Activatable(因为它扩展了SomethingElse)。那我就得叫这两个超级。activate()和这个。thing的thingParentActivate()。activate(),所以如果可能的话,我想避免这种模式。

有没有其他选择?

(链接到打字操场上的代码:https://www.typescriptlang.org/play?#code/IYIwzgLgTsDGEAJYBthjAggvAlgN2AlGQFMBvAWACgFaEAHKfQkhOCZiEgEwC4EQAe0GlgAOwQBeBADNgyMCQDc1OkkFjIUAK7xBUABQBKMgF9VdetpDIcsNrgJdj-PIJzcElGmroQAFjhgAHTsnDxSCNDayha6poiJMHIggDmBgDk2BxOxKxhTjyZRhbmVOXUKGgYAMqCALYkAThiaQCiCuSmKlTUrVxQcrCsACqBbQAKuFAkYogkAB5cYtwYOZz5ZtRVqOgI461p07PzCEsrawj1TS1tnYRealY2dg65LC4Ibh5ecb4GFoYNBYRyEFJGUJg5xGXrxWikRDAbjcG4kABq8hiAAkSLNItFYj54rANGAkil0llDm0GDM5kjocVSsSEOVKlRqvsaWlzss5lceScGX9TNNE9IYTP81GBtPQ8cZ-uVntZbPZCp8jK53J4nvD

共有1个答案

养鸿运
2023-03-14

正如你所知道的,JavaScript类不支持多重继承,所以如果你想得到那样的效果,你需要做一些事情来模拟它。Mixins是实现这一点的一种方式,但是它们并不真正支持有冲突的方法名。如果你有冲突的方法名,那么mixins将会破坏所有的方法名,只留下一个,这不是你想要的。

如果要在子类的实例上调用特定的超类的方法,可以直接使用Function.prototype.call(),该实例作为thisarg。而不是Activatable::activate(),您可以调用Activatable.prototype.activate.call(this);

让我们试一试:

interface ThingParent extends Activatable { }
class ThingParent extends SomethingElse {
    public activate(): void {
        Activatable.prototype.activate.call(this);
        let addSomeValueHere = true;
        console.log('Thing parent activated')
    }
}

class Thing extends ThingParent {
    constructor() {
        super()
    }
    public activate(): void {
        ThingParent.prototype.activate.call(this);
        console.log('Thing activated');
    }
}

let thing = new Thing();
thing.activate();
// [LOG]: "Activatable activated" 
// [LOG]: "Thing parent activated" 
// [LOG]: "Thing activated" 

这会编译好并产生您期望的输出。

在更复杂的场景中,您可能会决定需要混合使用直接方法调用或其他方法。

代码的游乐场链接

 类似资料:
  • 我正在为一个系统建模,该系统有一个创建资源的操作和其他消耗该资源的操作。然而,一个给定的资源只能被消耗一次——有没有一种方法可以保证在编译时这样做? 具体来说,假设第一个操作烘焙蛋糕,还有另外两个操作,一个用于“选择吃”蛋糕,另一个用于“选择吃蛋糕”,我只能做其中一个。 通过在我们使用蛋糕后在蛋糕上设置一个标志,很容易在运行时强制执行不保留已经吃过的蛋糕(反之亦然)的限制。但是有没有办法在编译时强

  • 问题内容: 我正在使用felixge的客户端。我没有使用ORM。 我正在用Vows进行测试,并且希望能够使用Sinon来模拟我的数据库。由于除之外我本身还没有DAL ,因此我不确定如何执行此操作。我的模型大多是带有很多吸气剂的简单CRUD。 关于如何做到这一点的任何想法? 问题答案: 使用sinon,您可以在整个模块上放置一个模拟或存根。例如,假设模块具有一个功能: ,是您期望的输入。是您期望的输

  • 我想现在,如果有可能模仿一个类一样 我们的业务逻辑在代码中的某个地方用< code>new myClass()创建了这个对象,因此我不能访问创建的对象来模拟这些方法。有没有办法替换整个类或者覆盖那些方法。我正在使用mockito,我只找到了这样做的例子 我们不能使用 PowerMock,因为它与我们的测试环境不兼容。 欢迎任何建议。

  • 我有折叠代码: 根据以下链接中描述的原因,我无法使用

  • 我有一个python项目,我使用virtualenv(pipenv)设置它。我使用来创建虚拟环境,并从它们内部使用 主要的派克 我试图显示一个情节,但我得到以下错误: 文件“/home/linuxbrew/.linuxbrew/opt/python@3.8/lib/python3。8/tkinter/init。py“,第36行,在导入_tkinter中#如果这失败,您的Python可能不会为Tk

  • 在虚拟环境之外,它运行良好。但是在虚拟环境中,MySQL Python连接器没有导入。我正在做覆盆子皮。下面是我提到的内容。我该怎么做才能修好它? =========================================================================== ==================================================