繁体   English   中英

创建多个抽象类javascript ES6

[英]Creating multiple abstract classes javascript ES6

今天,我想到了一个使用Proxy对象的想法,以允许创建多个抽象类,例如

const abstract = abstractClass => new Proxy(abstractClass,{
  construct: (target, args) => { throw new Error('Error, class was declared as abstract!') }
});

class A{}
class B{}
class C{}
[A,B,C] = [A,B,C].map(c => abstract(c));

所以我的问题是这种解决方案是否有缺点,如果有的话,它们是什么。

缺点是Proxy不能可靠地在ES5中进行多填充,并且速度很慢。

一个好的方法就是用继承来解决这个问题:

class Abstract {
    constructor() {
        if (Object.getPrototypeOf(this.constructor) === Abstract
            || this.constructor === Abstract) {
            throw new Error("Cannot instantiate abstract class");
        }
    }
};

class AbstractFoo extends Abstract {...}

class ConcreteFoo extends AbstractFoo {...}

直接实例化AbstractAbstractFoo将引发错误。

ES.next装饰器可用于简化任务:

function abstract(target) {
    return class Abstract extends target {
        constructor(...args) {
            super(...args);
            if (this.constructor === Abstract) {
                throw new Error("Cannot instantiate abstract class");
            }
        }
    };
}
@abstract
class AbstractFoo {...}

class ConcreteFoo extends AbstractFoo {...}

由于装饰器基本上是辅助函数,因此可以直接在纯ES6中应用:

const AbstractFoo = abstract(class AbstractFoo {...});

class ConcreteFoo extends AbstractFoo {...}

请注意,在装饰器的情况下,将在抛出错误之前对原始构造器进行评估,这是使用extends的代价。 解决方法是使用函数而不是类,并手动从target继承它,类似于TypeScript __extendsBabel __inherits帮助函数,这样可以在super()之前引发错误。 另一个解决方法是使用new.target (当前无法使用Babel转换为ES5):

function abstract(target) {
    return class Abstract extends target {
        constructor(...args) {
            if (new.target === Abstract) {
                throw new Error("Cannot instantiate abstract class");
            }
            super(...args);
        }
    };
}

一种更干净的方法是使用TypeScript(如注释中所建议),它引入抽象类作为语言功能,并在设计时进行处理。 这允许不污染原型链。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM