Есть ли способ наследовать параметры от конструктора родительского класса? - PullRequest
2 голосов
/ 29 мая 2019

У меня проблема в том, что у меня есть несколько базовых (универсальных) классов, свойства которых инициализируются через конструктор класса. Затем, когда я иду расширять этот класс, чтобы создать более конкретный класс, я должен заново ввести те же параметры, что и у конструктора базового класса, просто чтобы я мог передать их в 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;
    }
}

Ответы [ 2 ]

4 голосов
/ 29 мая 2019

Вы не можете наследовать, но вы можете ссылаться на параметр, используя 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  

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

1 голос
/ 29 мая 2019

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

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

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

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