Ответы пользователя по тегу ООП
  • Как избежать дубликации кода реализуя Trait'ы в Rust?

    bingo347
    @bingo347
    Crazy on performance...
    Написать derive макрос. Правда стоит соизмерить трудозатраты.
    Или написать обычный декларативный макрос (не так гибко как derive, но написать проще).

    А вообще, Rust не Java/C#, trait - не интерфейс.
    Если приведете не абстрактные примеры, вполне возможно, что задача решается проще.
    Ответ написан
    Комментировать
  • Почему определение инкапсуляции дают неправильно?

    bingo347
    @bingo347
    Crazy on performance...
    Цель инкапсуляции это объединение объектов
    кто Вам такое сказал?
    Само слово инкапсуляция происходит от латинского "in capsula", что можно перевести как "закрытый в коробке".
    Цель инкапсуляции - это сокрытие сложности. Не информации, не данных, не кода, а именно сложности.

    Вот представьте, у Вас есть лампочка с выключателем. Вы можете просто нажать на выключатель чтобы включить или выключить ее. Вам не нужно понимать электрические схемы внутри этого устройства, чтобы у Вас был свет. Вам достаточно пользоваться простым интерфейсом - выключателем. Это и есть инкапсуляция. Внутреннее устройство лампочки с выключателем инкапсулировано от Вас.
    Ответ написан
  • Как вернуть из массива инстансов классов значение объекта?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Если правильно понял, то:this.questions[0].questionText
    Ответ написан
    Комментировать
  • Различия MVC и Three Tier?

    bingo347
    @bingo347
    Crazy on performance...
    MVC вообще не рассматривает слой данных, зато разделяет клиентский слой на View (что показываем пользователю, например HTML и CSS в web, а так же их изменение во времени) и на Controller (обработчики внешних событий, клики мыши, нажатия клавиатуры, запросы извне).
    Model (бизнес модель, то как бизнес правила отражены в коде, собственно это и есть логика) действительно совпадает по своей сути со слоем логики.
    Слой данных не выражен в MVC, но он полезен, ибо действительно не надо смешивать домен с деталями, а работа с данными (БД, файлы, внешние API) - это детали, которые более подвержены изменениям во времени чем бизнес правила. А значит отделив этот слой мы инвестируем время в будущее, упростив поддержку ПО в будущем.
    Ответ написан
    Комментировать
  • Как описать обобщённый ответ с restful api сервера?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    Используйте дженерик параметры
    export type ApiResponse<T> =
      | { errors: Array<{ [key: string]: string }> }
      | { data: Array<T> }
      | { text: string };

    abstract class Api<T> {
      protected readonly baseUrl: string;
      protected readonly endPoint: string;
    
      protected get url(): string {
        return new URL(this.endPoint, this.baseUrl).toString();
      }
    
      protected constructor(baseUrl = '/', endPoint: string) {
        this.baseUrl = baseUrl;
        this.endPoint = endPoint;
      }
    
      protected async http({
        url = '',
        method = 'GET',
        data = undefined,
      }: RequestData): Promise<ApiResponse<T>> {
        try {
          const response: Response = await fetch(
            (new URL(url, this.url).toString()),
            { method, body: data }
          );
          return await response.json();
        } catch (e) {
          console.error(e.message);
          return { text: e.message };
        } finally {
          // finnally
        }
      }
    }

    class ApiPost extends Api<Post> {
      constructor(baseUrl: string, endPoint: string) {
        super(baseUrl, endPoint);
      }
    
      async list(count?: number): Promise<false | Array<Post>> {
        const response: ApiResponse = await this.http({
          url: `${count ? `?_limit=${count}` : ''}`,
        });
    
        if (Array.isArray(response))
          return response;
    
        return false;
      }
    }
    Ответ написан
    4 комментария
  • Как в javascript импортировать класс?

    bingo347
    @bingo347
    Crazy on performance...
    const {Shop} = require('Shop');
    const shop = new Shop();


    Ну и пару замечаний:
    1. Вместо product["id"], product["name"] можно писать product.id, product.name, поля же известны заранее, незачем усложнять
    2. newProducts должен быть объектом {}, а не массивом [], так как ключи - произвольные id, поле #products тоже у Вас не особо на массив похоже
    3. используйте let или const вместо var
    Ответ написан
    Комментировать
  • Для чего нужен полиморфизм?

    bingo347
    @bingo347
    Crazy on performance...
    Полиморфизм бывает разный:
    Полиморфизм подтипов - этот тип как раз таки и подразумевают в контексте ООП. Суть в том, что сущность некоторого класса так же может представляться базовым классом или интерфейсом. Это позволяет переиспользовать код, отдавая в один и тот же метод/функцию сущности с разными классами, но с общим интерфейсом.
    Параметрический полиморфизм - используется уже не только в ООП, но и в других парадигмах. Опять таки полиморфная функция принимает аргумент разных типов, при этом сам тип так же передается как параметр функции, а следовательно функция может оперировать составными типами на основе переданного. Или например возвращать результат того же или производного типа, сохраняя тем самым тип для вызывающего кода. Чаще всего представлено дженериками, но могут быть и другие формы (например template в C++). Как правило не имеет смысла в языках с динамической типизацией. А еще часто сопровождается контрактами на получаемый тип (например типами высшего порядка или типажами), что позволяет с одной стороны ограничить возможные типы, а с другой - воспользоваться характеристиками типа обусловленными контрактом.
    ad-hoc полиморфизм - способность функции предоставить разную реализацию в зависимости от запрашиваемой сигнатуры. Чаще всего выражено перегрузкой функций/методов. Как правило не реализуем средствами языка с динамической типизацией, хотя может быть реализован в рантайме (например в js функция всегда принимает произвольное количество аргументов и может проанализировать их в рантайме с помощью arguments).

    В общем случае полиморфизм нужен для переиспользования кода. Соблюдения практик SOLID и DRY не возможно без полиморфизма. Например в языке Go отсутствие полиморфизма в любом виде приводит к загрязнению кодовой базы и большому количеству копипасты.

    И еще, из моего ответа, может сложится мнение, что полиморфизм не применим к языкам с динамической типизацией, например к Python. На самом деле это не так, в ЯП с динамической типизацией полиморфизм наоборот возведен в абсолют.

    UPD: Примеры:
    правда я не шибко хорошо знаю конкретно Python, поэтому абстрактно напишу псевдокод:

    Полиморфизм подтипов, как уже говорил, это про ООП. Допустим у меня задача реализовать класс, который читает бинарные данные, проверяет, что они валидный utf-8 и выдает прочитанное как строку. Откуда он читает их? Да мне все равно, это не относятся к моей задаче. Конкретную реализацию я приму в аргументах, а уж откуда она будет читать, из файла или из сети - мне все равно. Главное чтоб эта реализация умела читать байты.
    // ok мне нужно что-то, что умеет читать байты, опишу это интерфейсом
    interface IByteReader {
      readBytes(): BytesIterator;
    }
    
    // и мой метод:
    readAsString(reader: IByteReader): string {
      var iterator: BytesIterator = reader.readBytes();
      // ну и тут как то с ним работаю, трансформируя байты в строку
    }
    теперь вызывающий код может передать в мой метод инстанс любого класса, реализующего мой интерфейс, и мне теперь не нужно дублировать логику чтения строки для файла и для сети.
    Еще один яркий пример тут - функция len() в Python, которая принимает любой тип реализующий одноименный магический метод.

    Параметрический полиморфизм, это про дженерики. Напишем 2 функции, обе будут принимать на вход массив, одна из них будет возвращать начальный элемент, а другая конечный. Но массивы бывают для элементов разных типов. Без параметрического полиморфизма, нам бы пришлось писать реализацию для каждого нужного типа, но благодаря ему мы можем это сделать в обобщенном виде:
    // T - это параметр типа
    fitst<T>(arr: [T]): Option<T> {
      if(arr.has(0)) return Some(arr[0]);
      else return None;
    }
    
    // давайте предположим, что некоторые виды массивов у нас могут быть бесконечными
    // тогда нам понадобится контракт, что можно передавать массивы только с известным размером
    last<T>(arr: [T]): Option<T>
      where [T]: WithKnownSize
    {
      var length: size = get_length(arr);
      if(length == 0) return None;
      else return arr[length - 1];
    }


    ad-hoc полиморфизм, это про перегрузку функций, пусть мы хотим функцию print которая умеет печатать числа и строки:
    print(value: string) {
      stdout.write(value);
    }
    print(value: int) {
      stdout.write(value.to_string());
    }
    Ответ написан
  • Инициализация конструктора в одну строку?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    const defaults = {
      title: 'wololo',
      status: 1
    };
    const keys = Object.getOwnPropertyNames(defaults);
    
    const validators = {
      status(value) {
        return !isNaN(value) && isFinite(value);
      }
    };
    
    const transforms = {
      status(value) {
        return parseInt(value);
      }
    };
    
    class MyClass {
        constructor(props) {
            for(let key of keys) {
                if(!Object.prototype.hasOwnProperty.call(props, key)) {
                  this[key] = defaults[key];
                  continue;
                }
                if(typeof validators[key] === 'function' && !validators[key](props[key])) {
                  this[key] = defaults[key];
                  continue;
                }
                this[key] = typeof transforms[key] === 'function' ? transforms[key](props[key]) : props[key];
            }
        }
    }
    Ответ написан
    4 комментария
  • Javascript не могу понять логики наследования?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    1й вариант принимает прототип родителя в параметре и возвращает отнаследованный прототип, что Вы будете с ним делать полностью на Вашей совести
    2й вариант принимает 2 конструктора и делает относительно правильное наследование
    Ответ написан
  • Javascript objects?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Почему так?
    this ссылается на контекст, в котором функция была вызвана
    test.otherSome(); //контекст - test
    test.otherSome.call(null); //контекст - null
    new test.otherSome(); //контекст - новый объект унаследованный от test.otherSome.prototype
    (0, test.otherSome)(); //контекст - undefined (в strict mode) или глобальный объект (не в strict mode)
    ({ otherSome: test.otherSome }).otherSome(); //контекст - объект который в скобочках

    ЗЫ. А как реализовать такую штуку...? Та которая не работает...

    Смотрите примеры выше, все кроме первого выкинут ошибку, что либо нельзя читать getText из null/undefined (2, 3 примеры), либо, что getText - не функция (3, 5 примеры)
    Ответ написан
    Комментировать
  • Почему не наследует свойство конструктора?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Во-первых, Object.create создает объект из прототипа без вызова конструктора, и передавать ему надо прототипconst add = Object.create(Manipulate.prototype);С вызовом конструктора надо писать так:const add = new Manipulate('id1', 'id2');

    Во-вторых, Object.prototype.hasOwnProperty проверяет, что данное свойство есть в объекте и оно собственное (не из прототипа), для общей проверки (включая цепочку прототипов) используется оператор inconsole.log('test' in add);

    UPD:
    Добавлю еще, что стрелочная функция не имеет собственного контекста, this у нее из замыкания, нужна полноценная функция или метод объекта
    Ответ написан
    Комментировать
  • JS Как имея название параметра внутри объекта найти его(просмотрев все вложенные объекты) и!!! получить к нему путь?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Хотя вопрос больше похож на "сделайте все за меня", сама задачка показалась мне интересной, вот решение:
    function findParamPath(obj, prop) {
        if(obj.hasOwnProperty(prop)) return prop;
        var props = Object.getOwnPropertyNames(obj);
        for(var i = props.length; i--; ) {
            if(typeof obj[props[i]] !== 'object') continue;
            var path = findParamPath(obj[props[i]], prop);
            if(path) return props[i] + '.' + path;
        }
        return null;
    }


    тестим:
    var obj = {
        object : {
            client : {
                name : 'Вася',
                phone : '799999999'
            },
            order : {
                param1 : '2122',
                param2 : '1231'
            }
        }
    };
    
    console.log(findParamPath(obj, 'name')); // 'object.client.name'
    console.log(findParamPath(obj, 'param1')); // 'object.order.param1'
    console.log(findParamPath(obj, 'unknown')); // null (не найдено)
    Ответ написан