Ответы пользователя по тегу ООП
  • Как обработать событие onClick кнопки, которая находится внутри другого компонента?

    HemulGM
    @HemulGM Куратор тега Delphi
    Delphi Developer, сис. админ
    В свойство ControlStyle у кнопки нужно добавить значение csClickEvents.
    newButton.ControlStyle := newButton.ControlStyle + [csClickEvents];
    Ответ написан
    Комментировать
  • Зачем нужен второй интерфейс в определении класса, если первый интерфейс - наследник второго?

    HemulGM
    @HemulGM
    Delphi Developer, сис. админ
    Потому что объект не будет считаться поддерживаемым родительский интерфейс одного из интерфейсов.

    Т.е. если объекту не указать Serializable и спросить, поддерживает ли он Serializable, то он скажет, что нет. Потому что он поддерживает только EntityRef, а не Serializable.

    Не знаю точно как в PHP, но так работает в некоторых языках. Т.е. наследование интерфейсов - это просто упрощение перечисления определений интерфейса.
    Ответ написан
  • Чем сервис отличается от объекта?

    HemulGM
    @HemulGM
    Delphi Developer, сис. админ
    Сервис - это часть одного из паттернов проектирования ООП. Обычно это такой класс, который реализует львиную долю логики программы. К которому обращаются все остальные классы.
    Объект - экземпляр класса.

    Это если речь про ООП.
    Также, сервис в разработке - это отдельная часть некого большого проекта, которая работает независимо и представляет собой отдельную программу или скрипт. Общение с которым реализуется через отдельное подключение, например http, ws или даже pipes
    Ответ написан
  • Что такое полиморфизм?

    HemulGM
    @HemulGM
    Delphi Developer, сис. админ
    Полиморфизм в программировании - это способность разные объекты использовать одинаково за счет механик наследования, переопределения методов и т.д..

    Например у тебя есть 3 класса описывающие разные сущности. Например, объект "новость", "бревно" и "картина". А ты хочешь вывести их в один список, да так чтобы показать более менее понятно, а не просто "новость 1" / "бревно 34".

    Для этого ты создаешь базовый класс, от которого наследуешь эти 3 класса и создаешь в нём абстрактный метод "описание". Теперь каждый класс должен будет реализовать этот метод (или может использовать родительскую реализацию, если создавать не абстрактный метод, а виртуальный) и по-своему выдать описание конкретного объекта. Примерно так же это реализуется через интерфейсы (interface).

    Т.е. мы можем иметь список объектов с типом элементов базового класса или интерфейса и знать, что есть метод "описание" и выводить его.

    На Ruby примера нет, могу на Delphi (Pascal)
    // Базовый класс для всех элементов
      TBaseItem = class
        // Наш метод, который позволяет получать описание объекта
        function GetDescription: string; virtual; abstract;
      end;
    
      // Класс картины
      TPicture = class(TBaseItem)
        // Свой метод получения описания картины
        function GetDescription: string; override;
      end;
    
      // Класс бревна
      TLog = class(TBaseItem)
        // Свой метод получения описания бревна
        function GetDescription: string; override;
      end;
    
      // Класс новости
      TNews = class(TBaseItem)
        // Свой метод получения описания новости
        function GetDescription: string; override;
      end;
    
      // Класс списка наших элементов, где каждый элемент имеет методы и поля базового класса TBaseItem
      TItems = class(TList<TBaseItem>);
    
      ...
      // Наш заполненый список, где у нас могут быть новости, бревна и прочие объекты на основе класса TBaseItem
      var Items: TItems;
    
      // Теперь мы можем пройтись по списку и получить описание всех объектов
      for var Item in Items do
        var Desc := Item.GetDescription;
    Ответ написан
  • Может кто-нибудь дать реальную задачу на которой можно применить ООП?

    HemulGM
    @HemulGM
    Delphi Developer, сис. админ
    Сколько фигни понаписали, а человек просто просил реальный пример для применения ООП.

    ООП помогает строить приложения так, как человеку удобнее мыслить. Наш мир окружают объекты. И в программировании мы описываем эти объекты. Например: человек - объект. Человека мы можем описать не целиком, если нам нужен человек только лишь как клиент. А для этого нам важен его идентификатор, имя и прочие данные.
    После чего мы используем списки таких объектов для манипуляции данных. Список клиентов - список объектов.

    Объекты могут совершать действия, или над объектами могут совершатся действия. Т.е. клиент сам может создавать заявку или этим может заниматься менеджер.

    Что то типа Client.CreateOrder (клиент создает заказ) или Orders.CreateOrder(Client) (менеджер заявок создает новую для такого-то клиента).
    Всё достаточно просто.

    Тебе достаточно придумать любую задачу и просто решить её с помощью объектов.
    Например, музыкальный плеер. Пусть трек будет представлять объект, содержащий путь к файлу, название, продолжительность и так далее. И список треков. Дальше сам решай кто чем будет управлять. Либо ты работаешь над списком объектов, либо каждый объект может сам делать что нужно. Но для музыкального плеера удобнее, когда треки лишь содержат данные (DTO). Т.е. имеем список треков и манипулируем объектами (добавляем, редактируем, удаляем и т.д.)

    Это в общих чертах. После чего добавляем наследование. Например, есть базовый класс - трек, но он может быть как ссылка на веб-ресурс, а может быть как файл. Т.е. мы создаем общий абстрактный класс для хранения любых треков в списке (как файловых, так и веб)

    TAudio = class abstract
    private
      FId: string;
    protected
      function GetTime: TTime;
      function GetName: string;
    public
      property Id: string read Fid write FId;  //Пусть тут будет полное имя файла или ссылка на веб
      property Time: TTime read GetTime;  //Время
      property Name: string read GetName;  //И имя
    end;

    После чего мы можем от него наследовать два класса (для файлов и для веб)
    TAudioFile = class(TAudio)
    protected
      function GetTime: TTime; override;
      function GetName: string; override;
    end;
    
    TAudioUrl = class(TAudio)
    protected
      function GetTime: TTime; override;
      function GetName: string; override;
    end;


    И хранить оба типа объектов в одном списке.
    TAudioList = TObjectList<TAudio>;

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

    Используя список мы можем
    var AudioList := TAudioList.Create;
    
    var Audio: TAudio := TAudioFile.Create('C:\Music\Track1.mp3');
    AudioList.Add(Audio);  // Добавлять аудио файлы
    
    Audio := TAudioUrl.Create('webmusic.ru/tracks/track1.mp3');
    AudioList.Add(Audio);  // Добавлять веб аудио 
    
    AudioList.Delete(0); // Удалять элементы
    
    // менять местами, сортировать, редактировать и т.д.


    Теперь у нас общий плейлист для тех и других видов аудио и мы можем скармливать их плееру для воспроизведения.

    Player.Play(AudioList[0].Id);

    А дальше мы можем усложнять и усложнять, добавляя новые возможности. Например, завести интерфейс и принимать аудио файлы из плагинов. Или использовать ОРМ для хранения плейлистов в базе данных. Мы можем отличать один вид от другого при переборе списка и обрабатывать уникально для некоторых.
    Ответ написан
    4 комментария
  • Что такое абстракция?

    HemulGM
    @HemulGM
    Delphi Developer, сис. админ
    Абстрактный класс в ООП - это не законченный класс, на основе которого нельзя создать объект, т.к. не всё описано.

    Например, как уже писали в ответах, возьмём класс "животное". Мы можем описать в нём общие для всех животных вещи, например методы перемещения или свойства "вид" или "биологический класс". Мы не можем инициализировать такой объект, т.к. нет просто существа "животное". А вот унаследованный класс "собака" от абстрактного класса "животное" можно создать. При этом мы можем иметь один список "животных" и обращаться к общим методам и свойствам, которые описаны в абстрактном классе.
    Абстрактный класс, как и интерфейс требует от дочернего класса реализовать всё, что описано в абстрактном классе, но не имплементировано, однако, может иметь и описанные готовые методы и свойства.
    Ответ написан
    Комментировать
  • Как контролировать двух телеграм ботов одним Python процессом?

    HemulGM
    @HemulGM Куратор тега Python
    Delphi Developer, сис. админ
    Запускать код ботов в разных потоках. У питона с этим так себе. Так что не дури, запускай два процесса.
    Ответ написан
  • Чем плохо использование статических функций в проекте для архитектуры?

    HemulGM
    @HemulGM
    Delphi Developer, сис. админ
    Плохо только не знание того, когда какой паттерн использовать. Вы - не знаете.
    Ответ написан
  • Как связывать класс с уточняющим классом?

    HemulGM
    @HemulGM
    Delphi Developer, сис. админ
    Есть класс - корабль. У корабля есть свойство - тип, т.е. просто поле Type.

    Знаешь тип - знаешь все параметры
    Ответ написан
    6 комментариев
  • ООП в javascript?

    HemulGM
    @HemulGM
    Delphi Developer, сис. админ
    Открываем книгу, читаем, что такое ООП.

    Не говоря уже о том, что js это всегда ООП
    Ответ написан
    Комментировать
  • Почему выдаёт ошибку PascalABC.NET при создании объекта?

    HemulGM
    @HemulGM
    Delphi Developer, сис. админ
    Потому что у тебя более новый паскаль, а не турбо паскаль.
    Использовать нужно слово class, а не object

    type Turburo = class
         country, date:string;
       duration, ex_price, putevka, kol_tourists, total_price: integer;
       ex: boolean;
       procedure create;
    end;
    Ответ написан
  • Лучший путь с точки зрения ООП?

    HemulGM
    @HemulGM
    Delphi Developer, сис. админ
    Использовать нужно свойства. При чем оставить только на чтение. В зависимости от языка, массив - это либо указатель, либо набор данных. Так что на твой вопрос абстрактно нельзя ответить.

    Например Delphi:
    type
      MyObject = class
      private
        FMyArray: array of string;
      public
        property Strings: array of string read FMyArray;
      end;


    Так мы ничего не теряем, но запрещаем изменять ссылку на массив. Хотя, сам массив ни кто тебе не запрещает изменять, если на него есть ссылка, но это уже проблемы указателей и отдельного языка.

    Для того, чтоб нельзя было вообще что-то делать с массивом, можно использовать следующую конструкцию:

    type
      MyObject = class
      private
        FMyArray: array of string;
        function GetMyArrayItem(Index: integer): string;
      public
        property Strings[Index: integer]: string read GetMyArrayItem;
      end;


    В таком случае, ссылки на массив нет. И изменить данные массива нельзя.
    Ответ написан
    Комментировать
  • Почему приватные свойства класса в dart все же доступны?

    HemulGM
    @HemulGM
    Delphi Developer, сис. админ
    В Dart нет специальных ключевых слов (public; private; protected) то есть спецификаторов доступа, по этому все идентификаторы «публичны» по умолчанию. Вопрос инкапсуляции решен соглашением: приватными считаются все члены класса, чье имя начинается с подчеркивания "_".


    Другими словами: приватность условна
    Ответ написан
    Комментировать
  • В каких случаях использовать приватные поля при определении класса?

    HemulGM
    @HemulGM
    Delphi Developer, сис. админ
    Вы здесь почти ничего осмысленного из ООП не используете. Пишу пример на паскале, но это ничего не меняет.

    Стандартным решением было бы создать базовый класс "Рисуемый", тот, который может быть отрисован на канве.
    Допустим TSprite. И объявим виртуальный метод Draw, чтобы мы могли попросить отрисываться.
    TSprite = class //ну или интерфейс
    public
      procedure Draw; virtual; abstract;
    end;

    Теперь напишем класс TRectangle на основе класса TSprite. Где тоже объявим метод Draw, но напишем там уже отрисовку. Ну и объявим приватные поля размеров и позиции с конструктором.
    TRectangle = class(TSprite)
    private
      FX, FY, FH, FW: Float;
      FCanvas: TCanvas;
    public
      procedure Draw; override;
      constructor Create(Canvas: TCanvas; const X, Y, H, W: Float); 
    end;
    
    constructor TRectangle.Create(Canvas: TCanvas; const X, Y, H, W: Float); 
    begin
      FCanvas := Canvas;
      FX := X;
      FY := Y;
      FH := H;
      FW := W;
    end;
    
    procedure TRectangle.Draw;
    begin
      FCanvas.Rectangle(FX, FY, FH, FW); // Это отрисовка фигуры на канве
    end;


    Теперь мы можем создавать класс TRectangle, указывать целевую канву и размеры.
    Rect := TRectangle.Create(Canvas, 10, 10, 40, 45);
    Rect.Draw; // Всё, можно отрисовать


    После всего этого мы можем создать другие фигуры или объекты, которые тоже будут наследоваться от TSprite. Сможем поместить их в список объектов типа TSprite и обращаться к каждому объекту через Draw. Например, в цикле отрисовки всех объектов.
    Ответ написан
    3 комментария
  • Вывести массив через класс?

    HemulGM
    @HemulGM
    Delphi Developer, сис. админ
    Так же как и без класса. Напиши метод в классе. В методы вывод массива. Вызови метод класса.
    Ответ написан
    Комментировать
  • Каким образом обрабатываются объекты в ООП?

    HemulGM
    @HemulGM
    Delphi Developer, сис. админ
    Основная суть ООП в объектах, которые сами могут управлять собой и выполнять действия над собой.
    МояМашина.ПовернутьНалево, а не ПовернутьМашинуНалево(МояМашина).

    Классы могут наследоваться. Мы можем иметь список объектов, например список транспорта (например, список будет состоять из объектов велосипедов, самолётов, легковых машин). Сами объекты могут иметь собственные методы, например,
    МойВелосипед.ПодтянутьСпицы; МойСамолёт.Приземлиться;
    которых нет у других, но могут иметь общие методы, например тот же поворот. И мы можем дать команду всему списку ПовернутьНалево.
    цикл для i от 0 до 100 делать СписокТранспорта[i].ПовернутьНалево.

    В списке транспорта, как я уже сказал и самолёты и вертолёты, но все они выполнят команду, т.к. все они будут наследоваться от класса Транспорт, который имеет метод ПовернутьНалево.
    Ответ написан
    3 комментария
  • Зачем использовать такую конструкцию в PHP?

    HemulGM
    @HemulGM
    Delphi Developer, сис. админ
    Используется он где угодно, если что
    Ответ написан
    Комментировать
  • Зачем присваивать переменную класса самой себе?

    HemulGM
    @HemulGM Куратор тега Python
    Delphi Developer, сис. админ
    Зачем присваивать переменную класса самой себе?

    В этом смысла нет.
    Смысл есть, если это не просто переменная, а свойство. Когда при присваивании может выполняться определённый код.
    Ответ написан
    Комментировать
  • Зачем нужна абстракция в ООП?

    HemulGM
    @HemulGM Куратор тега Python
    Delphi Developer, сис. админ
    Можно.

    Почему? Чтоб не создавали на основе абстрактного класса объекты.
    Чтобы интерпретатор тебе подсказал, что ты не описал такой-то метод (который абстрактный).
    Ответ написан
    Комментировать