Как обрабатывать статические заводские методы в дереве наследования

#javascript #typescript #inheritance

#javascript #typescript #наследование

Вопрос:

У меня есть иерархия наследования, где объекты могут быть либо сконструированы обычным образом с некоторыми значениями и некоторыми значениями по умолчанию, предоставляемыми различными конструкторами, либо могут быть сконструированы из сериализованной формы со всеми предоставленными значениями. Я хотел бы обрабатывать построение из сериализованной формы с помощью статических заводских методов, которые я определяю для каждого класса. Вот так:

 class A {
  constructor(x: number) {
     this.x = x;
  }

  static fromValues(v: {x: number}) {
    return new A(v.x);
  }
}

class B extends A {
  constructor(y: number) {
    super(0);
    this.y = y;
  }

  static fromValues(v: {x: number, y: number}) {
    // what goes here
  }
}

class C extends B {
  constructor(z: number) {
    super(0, 1);
    this.z = z;
  }

  static fromValues(v: {x: number, y: number, z: number}) {
    // what goes here
  }
}
  

Вопрос в том, как мне реализовать эти методы? Также, предпочтительно, они бы переложили часть работы на статические фабричные методы суперкласса.

Комментарии:

1. Единственный способ, который будет работать так, как написано, — это если вы создадите каждый объект независимо и создадите иерархию вручную, затем установив каждый __proto__ . Очевидно, что вы не можете создавать экземпляры, используя new потому что вы жестко закодировали значения в super() вызовах.

2. Итак, я предполагаю, что, возможно, реальный вопрос заключается в следующем: как мне следует обрабатывать этот общий шаблон? (игнорируя пример кода) Даже если я переключу конструктор на принятие сериализованной формы и статические фабрики будут генерировать объекты по умолчанию, я думаю, что я все равно столкнусь с той же проблемой, если я хочу, чтобы значения по умолчанию оставались рядом с классами, к которым они относятся.

3. Пожалуйста, посмотрите мой ответ. Без кода это очень упрямая тема. Но вы увидите, как это работает ниже.

Ответ №1:

Это очень самоуверенная тема (фабрики в JavaScript). Приведенное ниже решение предоставляется «в натуральном виде» (записано как ваш вопрос), чтобы предоставить прямой ответ без мнения о других методах.

Обратите внимание, что типизации удалены из-за ограничения инструмента snippet.

Изменения включают добавление значений по умолчанию в список параметров конструктора. Это позволяет удалить жестко закодированные значения и при необходимости предоставить значения для конструкторов подклассов. Кроме того, в ваших статических методах требуются значения по умолчанию по той же причине.

Это позволяет создавать отдельные объекты или всю иерархию либо с помощью статического фабричного метода, ЛИБО с помощью new ключевого слова.

 class A {
  constructor(x = 0) {
    this.x = x;
  }

  static fromValues(v = {x:0}) {
    return new A(v.x);
  }
}

class B extends A {
  constructor(y = 0, x) {
    super(x);
    this.y = y;
  }

  static fromValues(v = {y:0, x:0}) {
    return new B(v.y, v.x)
  }
}

class C extends B {
  constructor(z = 0, y, x) {
    super(y, x);
    this.z = z;
  }

  static fromValues(v = {z:0, y:0, x:0}) {
    return new C(v.z, v.y, v.x);
  }
}

const a = A.fromValues({x: 3});
const b = B.fromValues({y: 2,x: 3});
const c = C.fromValues({z: 1,y: 2,x: 3});
const nv = C.fromValues();

console.log("A", a);
console.log("B", b);
console.log("C", c);
console.log("No Values", nv);