Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   ES6. Class constructor question (https://javascript.ru/forum/misc/81424-es6-class-constructor-question.html)

Nexus 25.11.2020 01:20

ES6. Class constructor question
 
Здравствуйте.

У меня условно абстрактный класс для работы с сетью, от которого наследуется множество классов различных моделей, пример:
/**
 * @abstract
 */
class AbstractHttpService {
    baseRouteName;
    
    constructor(baseRouteName) {
        if (baseRouteName) {
            this.baseRouteName = baseRouteName;
        }
    }
}

class ProductsHttpService extends AbstractHttpService {
    baseRouteName = 'product';
}


Решил вкорячить кэширование экземпляров http-сервисов и тут понял, что из конструктора абстрактного класса никак не получить значение свойства "ребенка" до его инициализации.

Скажите, пожалуйста, есть ли какой-нибудь способ получить из абстрактного класса значение свойства класса, который наследуется от этого самого абстрактного класса?

Вижу только одно решение: вместо объявления для ребенка значения свойства по умолчанию передавать в конструктор родителя это самое значение.

voraa 25.11.2020 08:24

Цитата:

Сообщение от Nexus
Скажите, пожалуйста, есть ли какой-нибудь способ получить из абстрактного класса значение свойства класса, который наследуется от этого самого абстрактного класса?

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

Только так

class AbstractHttpService {
    baseRouteName;
     
    constructor(baseRouteName) {
        this.baseRouteName = baseRouteName;
    }
}
 
class ProductsHttpService extends AbstractHttpService {
    constructor(baseRouteName) { super (baseRouteName)}
}

Nexus 25.11.2020 15:18

Цитата:

Сообщение от voraa
И то, что js глотает такую конструкцию - это скорее бага, чем фитча.

В переопределении значения свойства базового класса не вижу ничего такого.
В каких языках переопределение свойства базового класса приведет к ошибке?

voraa 25.11.2020 16:36

Ну в C++ переобъявить просто не удастся. Будет поле в базом классе и поле с таким же именем в наследнике.
В js с методами так работает, а вот со свойствами нет. Свойство будет одно.

Вроде ошибки нет, но фигня может получиться. Если я беру чужой базовый класс, то придется скурпулезно изучить, какие у него поля, что бы случайно не написать такое же имя и работать с ним, как со своим.
Приватные свойства спасают. Там будет у базового класса свое, у наследника свое. Но из наследника к свойству базового не обратиться. protected в js еще не придумали.

Nexus 25.11.2020 17:54

voraa, если и в других языках ошибки нет, значит в и js это все-таки не бага.

Цитата:

Сообщение от voraa
Если я беру чужой базовый класс, то придется скурпулезно изучить, какие у него поля, что бы случайно не написать такое же имя и работать с ним, как со своим.
Приватные свойства спасают. Там будет у базового класса свое, у наследника свое. Но из наследника к свойству базового не обратиться. protected в js еще не придумали.

Я не совсем нуб, чутка в программирование умею)

ps. в php базовый класс может работать со свойствами наследника прямо из конструктора и, имхо, это очень удобно, не нужно нагружать конструктор метода всяким мусором или каким-либо другим способом передавать классу его "настройки".

voraa 25.11.2020 18:09

Цитата:

Сообщение от Nexus
в php базовый класс может работать со свойствами наследника прямо из конструктора

Это как?
Но даже если знать, что у наследника должно быть поле с определенным именем, то в js сначала выполняется конструктор базового класса, а потом конструктор наследника. И при работе конструктора базового, полей наследника просто не существует.

Nexus 25.11.2020 20:10

Цитата:

Сообщение от voraa
Это как?

http://sandbox.onlinephpfunctions.co...f43864b2b53300

<?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"

voraa 25.11.2020 23:58

Почти изящное решение
/**
 * @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)

Nexus 26.11.2020 00:37

voraa, я уже заменил переопределение свойства базового класса в наследуемом классе на передачу аргумента в конструктор.

Спасибо за пример решения, не знал, что у оператора new есть свойство target.

voraa 26.11.2020 07:17

Я даже не знаю, как назвать конструкцию new.target. В документациях это называется мета-свойство. Вроде как в Js у операторов не бывает свойств и ничего другого вида <оператор>.<свойство> не встречается. Просто данность такая.


Часовой пояс GMT +3, время: 05:02.