Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 25.11.2020, 01:20
Профессор
Отправить личное сообщение для Nexus Посмотреть профиль Найти все сообщения от Nexus
 
Регистрация: 04.12.2012
Сообщений: 3,791

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

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

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


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

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

Вижу только одно решение: вместо объявления для ребенка значения свойства по умолчанию передавать в конструктор родителя это самое значение.
Ответить с цитированием
  #2 (permalink)  
Старый 25.11.2020, 08:24
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,745

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

Только так

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

Последний раз редактировалось voraa, 25.11.2020 в 09:09.
Ответить с цитированием
  #3 (permalink)  
Старый 25.11.2020, 15:18
Профессор
Отправить личное сообщение для Nexus Посмотреть профиль Найти все сообщения от Nexus
 
Регистрация: 04.12.2012
Сообщений: 3,791

Сообщение от voraa
И то, что js глотает такую конструкцию - это скорее бага, чем фитча.
В переопределении значения свойства базового класса не вижу ничего такого.
В каких языках переопределение свойства базового класса приведет к ошибке?
Ответить с цитированием
  #4 (permalink)  
Старый 25.11.2020, 16:36
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,745

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

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

Последний раз редактировалось voraa, 25.11.2020 в 17:13.
Ответить с цитированием
  #5 (permalink)  
Старый 25.11.2020, 17:54
Профессор
Отправить личное сообщение для Nexus Посмотреть профиль Найти все сообщения от Nexus
 
Регистрация: 04.12.2012
Сообщений: 3,791

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

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

ps. в php базовый класс может работать со свойствами наследника прямо из конструктора и, имхо, это очень удобно, не нужно нагружать конструктор метода всяким мусором или каким-либо другим способом передавать классу его "настройки".
Ответить с цитированием
  #6 (permalink)  
Старый 25.11.2020, 18:09
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,745

Сообщение от Nexus
в php базовый класс может работать со свойствами наследника прямо из конструктора
Это как?
Но даже если знать, что у наследника должно быть поле с определенным именем, то в js сначала выполняется конструктор базового класса, а потом конструктор наследника. И при работе конструктора базового, полей наследника просто не существует.
Ответить с цитированием
  #7 (permalink)  
Старый 25.11.2020, 20:10
Профессор
Отправить личное сообщение для Nexus Посмотреть профиль Найти все сообщения от Nexus
 
Регистрация: 04.12.2012
Сообщений: 3,791

Сообщение от 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"
Ответить с цитированием
  #8 (permalink)  
Старый 25.11.2020, 23:58
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,745

Почти изящное решение
/**
 * @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)
Ответить с цитированием
  #9 (permalink)  
Старый 26.11.2020, 00:37
Профессор
Отправить личное сообщение для Nexus Посмотреть профиль Найти все сообщения от Nexus
 
Регистрация: 04.12.2012
Сообщений: 3,791

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

Спасибо за пример решения, не знал, что у оператора new есть свойство target.
Ответить с цитированием
  #10 (permalink)  
Старый 26.11.2020, 07:17
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,745

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



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Динамические элементы формы rustleofstars Элементы интерфейса 5 18.10.2019 19:57
ES6. Create class instance by name Nexus Общие вопросы Javascript 9 17.10.2018 16:50
Выполнение <script> При определенном class ilya1099 Javascript под браузер 0 06.11.2016 23:12
Использование классов в JavaScript devote Ваши сайты и скрипты 70 01.02.2013 17:17
Как работает функция Class godofjavascript Оффтопик 58 17.12.2012 09:49