Есть ли способ наследовать параметры от конструктора родительского класса?

Проблема, с которой я столкнулся, заключается в том, что у меня есть некоторые базовые (общие) классы, свойства которых инициализируются через конструктор класса. Когда я затем перехожу к расширению этого класса, чтобы создать более конкретный класс, я должен повторно ввести те же параметры, что и конструктор базового класса, чтобы я мог передать их в super. Если вы представите очень общий класс, у которого есть много свойств, которые инициализируются через конструктор, и который довольно часто расширяется, необходимость постоянно повторно набирать все эти свойства, чтобы каждый раз передавать их в super, кажется неэффективной. Я, вероятно, упустил какой-то общий способ предотвратить это. Есть идеи, как сделать это более эффективным? Возможно, каким-то образом «унаследовав» параметры конструктора родительского класса?

Вот пример кода, и, как вы можете видеть, в конструкторе Programmer мне нужно снова ввести name, age и height, чтобы передать его super:

class Person {
    name: string;
    age: number;
    height: number;

    constructor(name: string, age: number, height: number) {
        this.name = name;
        this.age = age;
        this.height = height;
    }
}

class Programmer extends Person {
    languages: string[];

    constructor(name: string, age: number, height: number, languages: string[]) {
        super(name, age, height);

        this.languages = languages;
    }
}

person Guy Bartkus    schedule 29.05.2019    source источник
comment
Вы можете иметь значение по умолчанию для этого параметра, если это необязательные поля для создания экземпляра Programmer.   -  person Raja Jaganathan    schedule 29.05.2019
comment
Программист - это человек, поэтому у него есть имя, возраст, другие поля, поэтому предполагается, что они инициализируются при создании класса. Сделайте то, что необязательно, и создайте экземпляр программиста на основе того, что необходимо.   -  person Eldho    schedule 29.05.2019


Ответы (2)


Вы не можете наследовать, но вы можете ссылаться на параметр, используя ContructorParameters, и вы можете распространить их обратно в производном конструкторе, если вы не против добавления каких-либо новых параметров впереди:

class Person {
    name: string;
    age: number;
    height: number;

    constructor(name: string, age: number, height: number) {
        this.name = name;
        this.age = age;
        this.height = height;
    }
}

class Programmer extends Person {
    languages: string[];

    constructor(languages: string[], ...p: ConstructorParameters<typeof Person>) {
        super(...p);

        this.languages = languages;
    }
}

new Programmer(["A"], "", 1, 1) // Since 3.4 you will get actual parameter names in intelisense not just ...p  

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

person Titian Cernicova-Dragomir    schedule 29.05.2019
comment
Спасибо, это весьма полезно :) - person Guy Bartkus; 29.05.2019
comment
Если кому-то из будущего интересно, вы можете резюмировать решение моей проблемы с параметрами остатка фразы. - person Guy Bartkus; 30.05.2019
comment
Не могу редактировать предыдущий комментарий, но я должен был указать оператор спреда, а не параметры отдыха. - person Guy Bartkus; 06.10.2019

Поскольку Person является базовым классом, который не может быть инициализирован без name, age и height, расширенному классу Programmer обязательно потребуются те же аргументы конструктора.

Как вы упомянули, в случае, если есть много аргументов, вы можете использовать шаблон создания (например, шаблон построителя) для создания объекта расширенного класса.

Если вам не нужен конструктор arg, вы можете сделать параметр суперконструктора необязательным.

class Person {
  name: string;
  age: number;
  height: number;

  constructor(name?: string, age?: number, height?: number) {
      this.name = name;
      this.age = age;
      this.height = height;
  }
}


class Programmer extends Person {
  languages: string[];

  constructor(languages: string[]) {
      super();

      this.languages = languages;
  }
}
person Plochie    schedule 29.05.2019
comment
Как это должно работать, особенно с this.languages = languages;? - person burtek; 29.05.2019