如何使用属性子集实现类?

时间:2016-07-01 17:40:34

标签: javascript design-patterns typescript ecmascript-6

我有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和class3(JavaScript中不支持多重继承,多重继承会给派生类4属性,但我只想要3)

  • class2具有class1属性的子集

  • class3具有class1属性的子集

问题:如何在JavaScript或TypeScript中最好地实现类,以便toClass2和toClass3转换方法有效?这有什么设计模式吗?谢谢

1 个答案:

答案 0 :(得分:1)

有很多方法可以实现您的需求,但您可能只展示了一个最小的示例,最佳方法取决于对您实际执行操作的更详细说明。

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

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

Sheet Q2

(与C类相同)

(2)使用接口:

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;
    }
}

然后您可以像上一种方法(code in playground)那样做:

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);
    }
}

(3)另一种方法是使用mixinscode 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;
    }
}

(4)您也可以使用Builder pattern,但一切都取决于您的情况。