【问题标题】:how do you implement classes with property subsets?你如何用属性子集实现类?
【发布时间】:2016-07-01 17:40:34
【问题描述】:

我有 3 节课...

class1 {
  constructor(a, b, c) {
    this.a = a;
    this.b = b;
    this.c = c;
    this.toClass2 = function() {
      // TODO: return this as an instance of class2;
      // the conversion would remove the unwanted 'b' property
    }
    this.toClass3 = function() {
      // TODO: return this as an instance of class3;
      // the conversion would remove the unwanted 'a' property
    }
  }
}

class2 {
  constructor(a, c) {
    this.a = a;
    this.c = c;
  }
}

class3 {
  constructor(b, c) {
    this.b = b;
    this.c = c;
  }
}

以下说法正确...

  • class1 可以扩展 class2
  • class1 可以扩展 class3
  • class1 不能扩展 class2 AND class3(JavaScript 不支持多重继承,多重继承会给派生类 4 个属性,但我只想要 3 个)

  • class2 具有 class1 属性的子集

  • class3 具有 class1 属性的子集

问题:我怎样才能最好地在 JavaScript 或 TypeScript 中实现类,以便 toClass2 和 toClass3 转换方法起作用?是否有任何设计模式?谢谢

【问题讨论】:

  • 你到底在问什么?什么不适用于您的转换方法?您打算如何使用这些课程?
  • 我想知道如何拥有一个提供返回其他类实例的方法的类。那些其他类将仅具有作为主类子集的属性。这不是它不起作用的情况 - 任何人都可以让它起作用 - 问题是最好的方法是什么

标签: javascript design-patterns typescript ecmascript-6


【解决方案1】:

有很多方法可以实现您所需要的,但您可能只是展示了一个最小的示例,而最好的方法取决于对您实际在做什么的更详细的解释。

一般来说,假设你的例子,这里有一些我能想到的方法。

(1)显而易见的方式(code in playground):

class A {
    private a: any;
    private b: any;
    private c: any;

    constructor(a: any, b: any, c: any) {
        this.a = a;
        this.b = b;
        this.c = c;
    }

    toB(): B {
        return new B(this.a, this.c);
    }
}

class B {
    private a: any;
    private c: any;

    constructor(a: any, c: any) {
        this.a = a;
        this.c = c;
    }
}

(与 C 类相同)

(2) 使用接口:

interface InterfaceBase {
    c: any;
}

interface InterfaceB extends InterfaceBase {
    a: any;
}

interface InterfaceC extends InterfaceBase {
    b: any;
}

interface InterfaceA extends InterfaceB, InterfaceC {
    a: any;
}

然后您可以像以前的方法 (code in playground) 一样做:

class B implements InterfaceB {
    a: any;
    c: any;

    constructor(a: any, c: any) {
        this.a = a;
        this.c = c;
    }
}

class A implements InterfaceA {
    a: any;
    b: any;
    c: any;

    constructor(a: any, b: any, c: any) {
        this.a = a;
        this.b = b;
        this.c = c;
    }

    toB(): InterfaceB {
        return new B(this.a, this.c);
    }

    toC(): InterfaceC {
        return new C(this.b, this.c);
    }
}

或者您可以使用可以自行转换的单个类 (code in playground):

class MyClass implements InterfaceA {
    a: any;
    b: any;
    c: any;

    constructor(meta: InterfaceA) {
        this.a = meta.a;
        this.b = meta.b;
        this.c = meta.c;
    }

    asB(): InterfaceB {
        return this as InterfaceB;
    }

    asC(): InterfaceC {
        return this as InterfaceC;
    }
}

(3)另一种方式是使用mixins(code in playground):

class HasA {
    _a: any;
    get a(): any {
        return this._a;
    }
    set a(value: any) {
        this._a = value;
    }
}

class HasB {
    _b: any;
    get b(): any {
        return this._b;
    }
    set b(value: any) {
        this._b = value;
    }
}

class HasC {
    _c: any;
    get c(): any {
        return this._c;
    }
    set c(value: any) {
        this._c = value;
    }
}

class ClassOne implements HasA, HasB, HasC {
    _a: any;
    a: any;
    _b: any;
    b: any;
    _c: any;
    c: any;

    constructor(a: any, b: any, c: any) {
        this.a = a;
        this.b = b;
        this.c = c;
    }
}
applyMixins(ClassOne, [HasA, HasB, HasC]);

function applyMixins(derivedCtor: any, baseCtors: any[]) {
    baseCtors.forEach(baseCtor => {
        Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
            derivedCtor.prototype[name] = baseCtor.prototype[name];
        });
    });
}

(4) 你也可以使用Builder pattern,但这一切都取决于你的场景。

【讨论】:

  • 我喜欢“或者您可以使用可以自行转换的单个类”方法 - 非常简洁明了 - 这种模式有名称吗?非常感谢您的帮助
  • 我不认为这是一种设计模式,至少不是我所知道的,更像是工作中的多态性
  • 非常感谢,给了我超出我想象的更多:)非常感谢 -
猜你喜欢
  • 2017-01-23
  • 2021-04-02
  • 2011-08-25
  • 1970-01-01
  • 1970-01-01
  • 2015-02-03
  • 1970-01-01
  • 1970-01-01
  • 2022-01-20
相关资源
最近更新 更多