Ответы пользователя по тегу ООП
  • Для чего все-таки нужны интерфейсы?

    vt4a2h
    @vt4a2h
    Senior software engineer (C++/Qt/boost)
    На самом деле, всё довольно просто: интерфейсы нужны для декомпозиции модели и облегчения разработки ПО. По факту, интерфейс описывает набор операций, который можно совершить над объектом. Если вы пишите какую-то функциональность, то она допустим работает только с теми объектами, над которыми можно совершать определённые действия, а что это за объекты вас не волнует. Буква "I" из набора принципов SOLID про этом, почитайте.

    Вот допустим я пишу модуль, который должен стучать, по всему тому, что можно постучать. Есть у меня функция "knock(IKnockable o)" ну и соответствующий интерфейс. Клиенты, кому надо воспользоваться этим модулем, реализуют этот интерфейс в своих классах и пользуются. Но мой модуль вообще ничего не знает об клиентах, он просто работает со всем, что реализует определённый протокол взаимодействия (интерфейс). Это ещё и связанность понижает.
    Ответ написан
  • Как использовать вектор классов?

    vt4a2h
    @vt4a2h Куратор тега C++
    Senior software engineer (C++/Qt/boost)
    Ну только такие методы не должны классу user принадлежать. Было бы лучше создать новый класс, вроде Database, который используется для хранения пользователей. А уж у этого класса можно сделать методы вроде find или sort. Только сигнатура этих методов уже разумеется никаких векторов не содержит: вектор -- это деталь реализации в данном случае, которая может быть изменена потом.
    Ответ написан
    Комментировать
  • Возможно ли улучшить пример LSP?

    vt4a2h
    @vt4a2h
    Senior software engineer (C++/Qt/boost)
    Тут есть проблема: во втором примере оба класса наследника абсолютно одинаковые. Т.е. пример ничего не показывает.

    Хорошим примером неправильного использования будет когда, например, один наследник кидает исключение, а другой нет. Ну и правильного, когда это не так. Ну или там усиление precondition покажите. Можете ещё показать проблему с бросанием разных типов исключений.
    Ответ написан
    Комментировать
  • Как правильно определить атрибуты при наследовании (c++, ООП)?

    vt4a2h
    @vt4a2h Куратор тега C++
    Senior software engineer (C++/Qt/boost)
    Можно сделать например так:
    #include <iostream>
    #include <iomanip>
    #include <memory>
    
    class ISomeInterface
    {
    public:
    	virtual bool isFoo() const noexcept = 0;
    };
    
    class Foo : public ISomeInterface
    {
    public: 
    	bool isFoo() const noexcept override { return true; }
    };
    
    class Bar : public ISomeInterface
    {
    public: 
    	bool isFoo() const noexcept override { return false; }
    };
    
    int main()
    {
    	// Or shared_ptr/make_shared
    	std::unique_ptr<ISomeInterface> foo = std::make_unique<Foo>();
    	std::cout << "Foo is Foo: " << std::boolalpha << foo->isFoo() << std::endl;
    	
    	// Or shared_ptr/make_shared
    	std::unique_ptr<ISomeInterface> bar = std::make_unique<Bar>();
    	std::cout << "Bar is Foo: " << std::boolalpha << bar->isFoo() << std::endl;
    	
    	return 0;
    }

    Ну и в методах не обязательно возвращать просто true/false, там может быть любая другая переменная.
    Ответ написан
  • Как избежать глаголов в наименовании классов?

    vt4a2h
    @vt4a2h
    Senior software engineer (C++/Qt/boost)
    Я вижу несколько подходов:
    1) Просто добавлять суффикс Data. На мой взгляд, не слишком описательно и довольно-таки общо.
    2) Название данных + операция. Например UserCreate, UserQuery, UserStatus и т.д. Но это не описывает сущность как класс данных.
    3) Комбинированный вариант: название + операция + идентификационный суффикс. Что-то вроде UserCreateData. По-моему, это выглядит наиболее приемлемо.
    Ответ написан
    Комментировать
  • Полиморфизм на собеседовании?

    vt4a2h
    @vt4a2h
    Senior software engineer (C++/Qt/boost)
    Я бы в ответ на такой вопрос, попросил бы его уточнить, т.к. не ясно, на каком уровне и что рассказывать. Вид полиморфизма, применительно к языку, на уровне теории?
    Ну и как вам тут верно написали, всё есть в книгах и на Вики.
    Ответ написан
    Комментировать
  • Можно ли как-то в c++ узнать принадлежность объекта классу?

    vt4a2h
    @vt4a2h Куратор тега C++
    Senior software engineer (C++/Qt/boost)
    Зачем вам это? Есть полиморфизм, а касты -- это плохой стиль почти всегда.

    Можно много чего использовать, в том числе и тэги. В базовом классе создаёте перечисление, где каждый элемент -- тип наследника + 1 элемент на тип базового класса. В базовом классе определяете виртуальный метод вроде type() и реализуете его для всех наследников.

    Но перед тем, как сделать это, хорошо подумайте над тем, надо ли оно вам. Про SOLID почитайте, в особенности про букву L.
    Ответ написан
    Комментировать
  • Прикладное применение интерфейсов?

    vt4a2h
    @vt4a2h
    Senior software engineer (C++/Qt/boost)
    Две последние буквы SOLID для вас ( https://en.wikipedia.org/wiki/SOLID_(object-orient... ). Вообще рекомендую прочитать всю эту статью, она очень дельная (+ все ссылки из секции Design and development principles). Использование этих принципов позволят писать относительно неплохой код даже без понимания (которое приходит с опытом обычно). Кстати, в этих статьях должны быть ссылки на книги по ОО-проектированию (ну в любом случае они неплохо гуглятся).
    Необходимость в интерфейсах и абстрактных классах возникает в основном в больших коммерческих проектах. Использование интерфейсов позволяет понизить связанность компонентов системы (их уровень знания друг о друге), что, в свою очередь, позволяет легче модифицировать систему, работая в команде. Например пишет один программист какой-то класс для запуска задач и делает у него метод, который принимает интерфейс IRunnable (возможно с одним методом run()) и описывает контракт (правила, как метод run() должен себя вести). После этого, любому другому программисту достаточно будет реализовать интерфейс по контракту и он сможет пользоваться классом для запуска задач. При этом, класс для запуска задач вообще понятия не имеет о том что он запускает, ему важно знать, что это можно запустить, и любому другому классу нет необходимости знать, как его запускают, достаточно просто реализовать метод.
    Ответ написан
    Комментировать
  • Какой стиль ООП выбрать?

    vt4a2h
    @vt4a2h
    Senior software engineer (C++/Qt/boost)
    Вообще забудьте о дополнительном слове get -- это излишество.

    1) Всё ок, метод setItem чисто теоретически может возвращать и только что добавленный айтем, тут все зависит от того, как класс используется. Я не знаю можно ли так пхп, но метод может в принципе возвращать и this или ссылку сам на себя. Что может быть использовано для реализации патерна билдер, например.

    2) Плохо. Класс должен возврашать хранимый айтем, знать об его внутреннем представлении о каких-то его методах или полях ему совсем не нужно. Вернули айтем, потом у него и спрашивайте данные.

    3) Третий пример я не понял. Да, в целом у класса есть какие-то данные, то да, он может их вернуть. Это не проблема.

    PS То, о чём вы спрашиваете, называется OOD. К языку программирования это имеет немного отношения.
    PPS В следующий раз, задавайте вопросы по какой-нибудь более конкретной модели. Пара-тройка простеньких классов, описывающих, ну там, книжную полку, напрмиер, на которую можно поставить книгу и забрать. Ваш пример слишком абстрактный.
    Ответ написан
    Комментировать
  • Какую книжку выбрать для ознакомления с ООП и алгоритмами??

    vt4a2h
    @vt4a2h
    Senior software engineer (C++/Qt/boost)
    По алгоритмам читайте Седжвика или Кормена. + по основным алгоритмам и структурам данных можно вики почитать, если надо просто ознакомиться.
    По ООП, тут всё сложнее, наверно именно для общего ознакомления проще почитать соотвествующие разделы вики + узнать про паттерны проектирования, DDD, GRASP, SOLID и т.п.
    Вики, понятное дело, на английском.
    Ответ написан
    Комментировать
  • Стоит ли делать в таком случае базовый класс и наследоваться от него?

    vt4a2h
    @vt4a2h Куратор тега C++
    Senior software engineer (C++/Qt/boost)
    Если даные только для внутреннего пользования, то намного лучше создать структуру Data (имя можно менее общее) или две структуры, если данные нельзя скомпоновать по смыслу в одну структуру.
    Ну и наследовать все классы от QMainWindow это не очень правильно. Т.к. по смыслу в большинстве случаев главное окно одно. Этот класс отличается от обычного QWidget наличием дополнителных компонентов, добавленых по умолчанию (тулбар, например).
    Ответ написан
    2 комментария
  • ООП головного мозга?

    vt4a2h
    @vt4a2h Куратор тега C++
    Senior software engineer (C++/Qt/boost)
    С открытыми полями можно сделать разве что какую-нибудь структурку вроде std::pair, которая допустим откуда-то возвращается в качестве результата (например это результат вычислений и какой-нибудь тэг) или которая используется только в рамках одного класса или просто в одном cpp файле как вспомогательная, но не где более.
    В остальных случаях всегда нормальная инкапсуляция иначе потом будет плохо и вы будете страдать. Представьте ситуацию с большим проектом, когда вам нужно банально поставить бряку и посмотрять кто и когда изменил значение поля. Или например добавить любую логику перед установкой/получением значений (хотя бы банальные нотификации).
    Просто возьмите за правило инкапсулировать и все. Нажать пару кнопок для генерации методов лучше, чем потом страдать.
    Ответ написан
    Комментировать
  • Qt. Как сериализовать объекты содержащие коллекции?

    vt4a2h
    @vt4a2h Куратор тега C++
    Senior software engineer (C++/Qt/boost)
    Для сереализации в Qt есть специальный класс QDataStream. У классов которые вы хотите сереализовать нужно реализовать два оператора (для чтения и для записи):
    QDataStream &operator<< (QDataStream &out, const T &obj);
    QDataStream &operator>> (QDataStream &in, T &obj);
    
    QFile f("path");
    if (f.open(QIODevice::ReadOnly) { // or WriteOnly, or ReadWrite
       QDataStream s(&f);
       T obj;
       s >> obj; // for write s << obj
    }

    Но у вас в коллециях указатели, т.ч. сереализоваться будут адреса, а не сами объекты. Эту проблему нужно как-то решить, т.е. если у вас QList<Institution> lst, то можно просто написатьs << lstдля сереализации, а если указатель, то нет, возможно написать соотвествующий оператор для указателя -- это решение.

    А еще возможно стоит присмотреться к JSON (с пятой версии поддержка входит в стандартную библиотеку Qt) если нужно именно сохранять в файлы, потом читать и иметь возможность поправить руками.

    PS код писал просто по памяти, поэтому может не скомпилироваться :) Но примерно дела обстоят так.
    PPS и лучше используйте какие-нибудь умные указатели вроде QSharedPointer, boost::shared_ptr или std::shared_ptr (с C++11)... Голые указатели уже моветон.
    Ответ написан
    1 комментарий
  • Когда ооп быстрее процедурного?

    vt4a2h
    @vt4a2h
    Senior software engineer (C++/Qt/boost)
    Вообще вопрос довольно странный. Не знаю как там дела с PHP, но про C++ я бы сказал: профилировщик в руки, релизный билд и смотрите. Да и потом, насколько быстрее, критична ли производительность, что в приоритете -- производительность или поддержка и расширяемость... ? Обычно весь код и не требует оптимизации по скорости работы, только некоторые места (которые иногда хоть на ассемблере перепиши, а в силу особенности алгоритмов большей скорости не получишь).
    Ответ написан
  • Стоит ли использовать ооп?

    vt4a2h
    @vt4a2h
    Senior software engineer (C++/Qt/boost)
    Русский язык сначала освойте. PHP вам рановато.
    Ответ написан
    3 комментария
  • Наследование бинарной перегрузки?

    vt4a2h
    @vt4a2h
    Senior software engineer (C++/Qt/boost)
    dynamic_cast, static_cast, reinterpret_cast
    Ответ написан
  • Множественное наследование не нарушает ООП?

    vt4a2h
    @vt4a2h
    Senior software engineer (C++/Qt/boost)
    В вашем случае больше подойдёт агрегация. И, в качестве совета: всегда старайтесь рассматривать агрегацию как альтернативу множественного наследования. Почитайте что-нибудь хорошее по ООП (найдите в сети, есть 100500 ответов на вопрос "что почитать по теме ...").

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

    Если очень коротко:
    Интерфейс следуют рассматривать как описание набора похожих по смыслу действий, которые можно произвести с экземпляром класса. Например мы можем постучать по всему, реализует интерфейс IKnockable, и в контексте использования данного интерфейса нам не важны остальные характеристики объекта. Постучать, допустим можно по дереву, а можно и по голове.
    Понятие наследование от базового класса включает в себя наследование описательных и поведенческих характеристик. Допустим есть класс виджетов, которые умеют себя рисовать, реагировать на команды и прочее. Пусть от виджета наследуется класс MainWindow или класс Dialog. Эти классы умеют себя рисовать как и виджет, имеют свойства прозрачности (допустим) и прочие, однако содержат что-то новое элементы управления по умолчанию, предопределённые свойства модальности иное поведение и пр.
    Конечно неплохо было бы учесть некоторые принципы SOLID, но вопрос не про это...
    Ответ написан
    4 комментария
  • Зачем нужен ООП?

    vt4a2h
    @vt4a2h Куратор тега C++
    Senior software engineer (C++/Qt/boost)
    Вот вы говорите, что пользуетесь уже готовыми классами для решения каких-то задач... Прекрасно! А теперь попробуйте реализовать такую же функциональность, но без использования классов (и вообще ООП, т.к. это не только классы на самом то деле), а потом сравните код, который у вас получился с первичной ООП реализацией. Сравнивайте с точки зрения удобства использования, лёгкости сопровождения и восприятия другими разработчиками. Ещё можете сравнить с точки зрения тестирования и простоты добавления нового функционала.
    Думаю, что сразу поймёте зачем нужен ООП.

    PS
    Хотя, тут возможен вариант, что вы ещё не сталкивались с задачами, которые необходимо (ок, удобно) решать с использованием ООП... Так заодно и столкнётесь)
    Ответ написан
    Комментировать
  • Как число 12345 сделать строкой в QT?

    vt4a2h
    @vt4a2h
    Senior software engineer (C++/Qt/boost)
    Скорре всего никак, т.к. QT -- это скорее всего QuickTime, но никак не Qt.
    Ответ написан
  • Как организовать код через ООП для простой задачи?

    vt4a2h
    @vt4a2h
    Senior software engineer (C++/Qt/boost)
    На самом деле, написав программу с GUI вы, в большинстве случаев, уже использовали все механизмы ООП, даже если сами не написали ни одного класса. Но, думаю, что вашего преподавателя такой ответ не удовлетворит, поэтому вот несколько вариантов:
    1. Наследовать от базовых графических элементов и создать: класс игрового поля, клетки, содержимого клетки... И куда фантазия заведует. Полиморфным будет метод рисования, как минимум. На мой взгляд вариант плох.
    2. Наследовать от класса кнопки и реализовать соответствующие поведение: флажок там ставить на правый клик и т.д. Ну и при генерации поля кнопки будут просто размещаться в нужном порядке. Тут возможно придётся переопределить метод обработки событий для кнопки ну или что-то похожее сделать...
    3. Есть же у вас класс игры, вот и добавьте класс предка IGame, с виртуальным методом play(). Это быстро и решительно позволит использовать недостающие принципы ООП. Самый короткий, и печальный вариант) Но цель же сдать работу, как я понимаю.
    Ответ написан
    Комментировать