ES6. Class constructor question
Здравствуйте.
У меня условно абстрактный класс для работы с сетью, от которого наследуется множество классов различных моделей, пример:
/**
* @abstract
*/
class AbstractHttpService {
baseRouteName;
constructor(baseRouteName) {
if (baseRouteName) {
this.baseRouteName = baseRouteName;
}
}
}
class ProductsHttpService extends AbstractHttpService {
baseRouteName = 'product';
}
Решил вкорячить кэширование экземпляров http-сервисов и тут понял, что из конструктора абстрактного класса никак не получить значение свойства "ребенка" до его инициализации. Скажите, пожалуйста, есть ли какой-нибудь способ получить из абстрактного класса значение свойства класса, который наследуется от этого самого абстрактного класса? Вижу только одно решение: вместо объявления для ребенка значения свойства по умолчанию передавать в конструктор родителя это самое значение. |
Цитата:
И то, что js глотает такую конструкцию - это скорее бага, чем фитча. Не должны переобъявляться поля базовых классов в наследниках. Только так
class AbstractHttpService {
baseRouteName;
constructor(baseRouteName) {
this.baseRouteName = baseRouteName;
}
}
class ProductsHttpService extends AbstractHttpService {
constructor(baseRouteName) { super (baseRouteName)}
}
|
Цитата:
В каких языках переопределение свойства базового класса приведет к ошибке? |
Ну в C++ переобъявить просто не удастся. Будет поле в базом классе и поле с таким же именем в наследнике.
В js с методами так работает, а вот со свойствами нет. Свойство будет одно. Вроде ошибки нет, но фигня может получиться. Если я беру чужой базовый класс, то придется скурпулезно изучить, какие у него поля, что бы случайно не написать такое же имя и работать с ним, как со своим. Приватные свойства спасают. Там будет у базового класса свое, у наследника свое. Но из наследника к свойству базового не обратиться. protected в js еще не придумали. |
voraa, если и в других языках ошибки нет, значит в и js это все-таки не бага.
Цитата:
ps. в php базовый класс может работать со свойствами наследника прямо из конструктора и, имхо, это очень удобно, не нужно нагружать конструктор метода всяким мусором или каким-либо другим способом передавать классу его "настройки". |
Цитата:
Но даже если знать, что у наследника должно быть поле с определенным именем, то в js сначала выполняется конструктор базового класса, а потом конструктор наследника. И при работе конструктора базового, полей наследника просто не существует. |
Цитата:
<?php
abstract class AbstractHttpService {
protected string $baseRouteName;
public function __construct(?string $baseRouteName = null) {
if ($baseRouteName) {
$this->baseRouteName = $baseRouteName;
}
var_dump($this->baseRouteName);
}
}
class ProductsHttpService extends AbstractHttpService {
protected string $baseRouteName = 'product';
}
new ProductsHttpService();// string(7) "product"
|
Почти изящное решение
/**
* @abstract
*/
class AbstractHttpService {
baseRouteName;
constructor(baseRouteName) {
this.baseRouteName = baseRouteName ?? new.target.baseRouteName;
}
}
class ProductsHttpService extends AbstractHttpService {
static baseRouteName = 'product';
}
let x = new ProductsHttpService ()
console.log (x.baseRouteName)
|
voraa, я уже заменил переопределение свойства базового класса в наследуемом классе на передачу аргумента в конструктор.
Спасибо за пример решения, не знал, что у оператора new есть свойство target. |
Я даже не знаю, как назвать конструкцию new.target. В документациях это называется мета-свойство. Вроде как в Js у операторов не бывает свойств и ничего другого вида <оператор>.<свойство> не встречается. Просто данность такая.
|
| Часовой пояс GMT +3, время: 03:02. |