10 принципов ооп, о которых стоит знать каждому программисту

Введение

Почти все популярные языки программирования являются объектно-ориентированными. В таблице приведены данные о популярности языков (рейтинг TIOBE) за сентябрь 2019 года :

Не являются объектно-ориентированными лишь 20% — это языки программирования аппаратуры (Си, Assembly language), декларативный язык программирования баз данных (SQL) и визуальный язык MATLAB. Не удивительно, что почти в каждом описании вакансии программиста требуется что-то типа «Понимание ООП» или «Понимание принципов SOLID» (что очень близко).

ООП строится лишь на паре ключевых слов и синтаксических конструкций. Однако, понять ООП сложно уже потому, что его очень часто неправильно преподают в ВУЗах — об этом, в частности, можно прочитать там . Еще сложнее правильно пользоваться объектно-ориентированным программированием — помимо синтаксических конструкций оно подразумевает ряд принципов, призванных решить проблемы и обеспечить ценности.

В этой статье-учебнике:

  1. развития языков программирования, объясняющие существующую систему ценностей;
  2. на примерах показаны и их роль в обеспечении ценностей;
  3. приведены на материалы для дальнейшего изучения.

Для освоения материала, читатель должен иметь базовые навыки программирования на любом языке программирования и практику (хотя бы неудачную) применения классов.

Объект в ООП: определение

При рассмотрении задачи программирования на ОО-языке вместо вопросов о ее разделении на отдельные функции возникает проблема разделения на объекты. ООП-мышление намного облегчает разработку приложений. Это происходит в результате сходства программных и реальных объектов.

Какие вещи становятся объектами в ООП? Ниже представлены типичные категории.

Физический объект в ООП – это:

  • транспорт в моделях движения потока;
  • электрические элементы в программах схемотехники;
  • страны в модели экономики;
  • самолет в системе управления воздушным движением.

Элементы среды компьютера пользователя:

  • меню;
  • окна;
  • графика (линия, прямоугольник, круг);
  • клавиатура, мышь, принтер, дисковые накопители.

Люди:

  • работники;
  • студенты;
  • клиенты;
  • продавцы.

Данные:

  • книга учета;
  • личное дело;
  • словарь;
  • таблица широт и долгот населенных пунктов.

Связь объектов реального мира и ООП стало результатом сочетания функций и данных: они произвели переворот в программировании. Такого близкого соответствия в процедурных языках нет.

Роль наследования

Следующий принцип ООП — наследование — касается способности языка позволять
строить новые определения классов на основе определений существующих классов. По сути, наследование позволяет расширять поведение базового (или родительского) класса, наследуя основную функциональность в производном подклассе (также именуемом
дочерним классом):

Т.е. наследование представляет собой процесс, в ходе которого один объект приобретает свойства другого объекта. Это очень важный процесс, поскольку он обеспечивает
принцип иерархической классификации. Если вдуматься, то большая часть знаний
поддается систематизации благодаря иерархической классификации по нисходящей.

Если не пользоваться иерархиями, то для каждого объекта пришлось бы явно определять все его свойства. А если воспользоваться наследованием, то достаточно определить лишь те свойства, которые делают объект особенным в его классе. Он может также наследовать общие свойства своего родителя. Следовательно, благодаря механизму
наследования один объект становится отдельным экземпляром более общего класса.

Проблемы структурного программирования

Поскольку приложения становились все более крупными, структурное программирование начало испытывать трудности. Проекты становились слишком сложными. Графики сдвигались. Задействовалось большее число программистов. Сложность росла. Затраты взлетали, график сдвигался дальше, и наступал крах.

Анализ причин этих неудач показал недостатки процедурной парадигмы. Независимо от того, насколько хорошо реализован структурированный подход к программированию, крупные приложения становятся чрезмерно сложными.

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

Если рассматривать эти проблемы в контексте программы учета запасов, то одним из важнейших глобальных элементов данных является совокупность учетных единиц. Разные функции могут обращаться к ним для ввода нового значения, его отображения, изменения и т. д.

Неограниченный доступ

В программе, написанной, например, на C, есть два вида данных. Локальные скрыты внутри функции и другими процедурами не используются.

Когда две и более функций должны получить доступ к одним и тем же данным, то последние должны быть глобальными. Такими, например, являются сведения об учитываемых предметах. Глобальные данные могут быть доступны любой процедуре.

В большой программе есть множество функций и много глобальных элементов. Проблема процедурной парадигмы состоит в том, что это приводит к еще большему числу потенциальных связей между ними.

Такое большое количество соединений вызывает несколько затруднений. Во-первых, это осложняет понимание структуры программы. Во-вторых, затрудняет внесение изменений. Изменение в глобальном элементе данных может потребовать корректирования всех функций, имеющих к нему доступ.

Например, в программе учета кто-то решит, что код учитываемого предмета должен состоять не из 5 цифр, а из 12. Это потребует изменить тип данных с short на long. Теперь связанные с кодом функции должны быть изменены для работы с новым форматом.

Когда элементы изменяются в большом приложении, трудно сказать, какие процедуры имеют к ним доступ. Но даже если это выяснить, их изменение может привести к неправильной работе с другими глобальными данными. Все связано со всем остальным, поэтому изменение в одном месте аукнется в другом.

Инкапсуляция

Цель инкапсуляции — улучшить качество взаимодействия вещей за счет их упрощения.

А лучший способ упростить что-то — скрыть все сложное от посторонних глаз. Например, если вас посадят в кабину Боинга, вы не сразу разберетесь, как им управлять:

С другой стороны, для пассажиров самолета все выглядит проще: купил билет, сел в самолет, взлетели и приземлились. Вы можете с легкостью перелететь с континента на континент, обладая только навыками «купить билет» и «сесть на самолет». Все сложности в виде подготовки самолета к полету, взлета, посадки и различных внештатных ситуаций скрыты от вас. Не говоря уже о спутниковой навигации, автопилоте и диспетчерских центрах в аэропортах. И это упрощает нам жизнь.

С точки зрения программирования, инкапсуляция — это «сокрытие реализации». Мне нравится такое определение. Наш класс может содержать сотни методов и реализовывать очень сложное поведение в различных ситуациях. Но мы можем скрыть от посторонних глаз все его методы (пометить модификатором private), а для взаимодействия с другими классами оставить всего пару-тройку методов (пометить их модификатором public). Тогда все остальные классы нашей программы будут видеть в этом классе всего три метода и вызывать именно их. А все сложности будут скрыты внутри класса, как кабина пилотов от счастливых пассажиров.

Что не так с процедурным программированием

Про­це­дур­ное про­грам­ми­ро­ва­ние иде­аль­но рабо­та­ет в про­стых про­грам­мах, где все зада­чи мож­но решить, гру­бо гово­ря, десят­ком функ­ций. Функ­ции акку­рат­но вло­же­ны друг в дру­га, вза­и­мо­дей­ству­ют друг с дру­гом, мож­но пере­дать дан­ные из одной функ­ции в другую.

Тут при­хо­дит продакт-менеджер и гово­рит: «Хочу, что­бы поль­зо­ва­тель точ­но знал, в чём ошиб­ка при вво­де элек­трон­но­го адре­са». Теперь вам нуж­но научить функ­цию выда­вать не про­сто true — false, а ещё и код ошиб­ки: напри­мер, если в адре­се опе­чат­ка, то код 01, если адрес спа­мер­ский — код 02 и так далее. Это неслож­но реализовать.

Вы зале­за­е­те внутрь этой функ­ции и меня­е­те её пове­де­ние: теперь она вме­сто true — false выда­ёт код ошиб­ки, а если ошиб­ки нет — пишет «ОК».

И тут ваш код лома­ет­ся: все десять мест, кото­рые ожи­да­ли от про­ве­ряль­щи­ка true или false, теперь полу­ча­ют «ОК» и из-за это­го ломаются.

Теперь вам нужно:

  • либо пере­пи­сы­вать все функ­ции, что­бы научить их пони­мать новые отве­ты про­ве­ряль­щи­ка адресов;
  • либо пере­де­лать сам про­ве­ряль­щик адре­сов, что­бы он остал­ся сов­ме­сти­мым со ста­ры­ми места­ми, но в нуж­ном вам месте как-то ещё выда­вал коды ошибок;
  • либо напи­сать новый про­ве­ряль­щик, кото­рый выда­ёт коды оши­бок, а в ста­рых местах исполь­зо­вать ста­рый проверяльщик.

Зада­ча, конеч­но, реша­е­мая за час-другой.

Но теперь пред­ставь­те, что у вас этих функ­ций — сот­ни. И изме­не­ний в них нуж­но делать десят­ки в день. И каж­дое изме­не­ние, как пра­ви­ло, застав­ля­ет функ­ции вести себя более слож­ным обра­зом и выда­вать более слож­ный резуль­тат. И каж­дое изме­не­ние в одном месте лома­ет три дру­гих места. В ито­ге у вас будут нарож­дать­ся десят­ки кло­ни­ро­ван­ных функ­ций, в кото­рых вы сна­ча­ла буде­те раз­би­рать­ся, а потом уже нет.

Это назы­ва­ет­ся спагетти-код, и для борь­бы с ним как раз при­ду­ма­ли объектно-ориентированное программирование.

Ключевые преимущества

Основным достоинством ООП является то, что данная концепция позволяет значительно ускорить разработку новых программ и приложений, разделив общий объем работы между несколькими независимыми программистами или группами сотрудников. Код строится таким образом, что его отдельные логические блоки работают изолированно друг от друга и не могут помешать выполнению других функций.

Среди прочих аргументов в пользу использования объектно-ориентированного программирования можно выделить такие:

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

Объектно-ориентированные языки программирования поставляются с богатыми библиотеками объектов, а код, разработанный в ходе реализации проекта, также может быть повторно использован в будущем при создании других программ. Используя готовые библиотеки, вы можете еще больше ускорить процесс разработки, адаптируя и модифицируя для своих проектов уже существующие рабочие решения. Это особенно полезно при разработке графических интерфейсов пользователя. Поскольку объектные библиотеки содержат много полезных функций, разработчикам программного обеспечения не нужно “изобретать велосипед” так часто, что дает возможность максимально сосредоточиться на создании новой программы.

@ivashkevich

18.09.2019 в 07:43

4069

+10

История развития

Основа ООП была заложена в начале 1960-х годов. Прорыв в использовании экземпляров и объектов был достигнут в MIT с PDP-1, и первым языком программирования для работы с объектами стал Simula 67. Он был разработан Кристен Найгаард и Оле-Джохан Даль в Норвегии с целью создания симуляторов. Они работали над симуляциями взрыва кораблей и поняли, что могут сгруппировать корабли в различные категории. Каждому типу судна было решено присвоить свой собственный класс, который должен содержать в себе набор уникальных характеристик и данных. Таким образом, Simula не только ввела понятие класса, но и представила рабочую модель.

Термин «объектно-ориентированное программирование» был впервые использован Xerox PARC в языке программирования Smalltalk. Понятие ООП использовалось для обозначения процесса использования объектов в качестве основы для расчетов. Команда разработчиков была вдохновлена проектом Simula 67, но они спроектировали свой язык так, чтобы он был динамичным. В Smalltalk объекты могут быть изменены, созданы или удалены, что отличает его от статических систем, которые обычно используются. Этот язык программирования также был первым, использовавшим концепцию наследования. Именно эта особенность позволила Smalltalk превзойти как Simula 67, так и аналоговые системы программирования.

Simula 67 стала новаторской системой, которая впоследствии стала основой для создания большого количества других языков программирования, в том числе Pascal и Lisp. В 1980-х годах объектно-ориентированное программирование приобрело огромную популярность, и основным фактором в этом стало появление языка С++

Концепция ООП также имела важное значение для разработки графических пользовательских интерфейсов. В качестве одного из самых ярких примеров можно привести структуру Cocoa, существующую в Mac OS X

Общие принципы модели стали применяться во многих современных языках программирования. Некоторые из них — Fortran, BASIC, Pascal. На тот момент многие программы не были разработаны с учетом ООП, что было причиной возникновения некоторых проблем совместимости. “Чистые” объектно-ориентированные языки программирования не обладали многими функциями, необходимыми программистам. Для решения этих проблем ряд исследователей предложили несколько новых языков программирования, созданных на основе принципов ООП с сохранением других, необходимых программистам, функций. Среди наиболее ярких примеров можно выделить Eiffel, Java, .NET. Даже в серьезных веб-разработках используются языки программирования, основанные на принципах ООП — PHP (у нас вы можете пройти курс ООП в PHP), Python, Ruby. По мнению экспертов, в ближайшие несколько десятилетий именно объектно-ориентированный подход будет оставаться основной парадигмой в развитии программирования.

Класс

Классы, в некотором смысле, подобны чертежам: это не объекты сами по себе, а их схемы. Класс «банковских счетов» имеет строго определенные и одинаковые для всех атрибуты, но объекты в нём – сами счета – уникальны.

Как в Python создать класс

В Python классы и объекты по смыслу не отличаются от других языков. Нюансы в реализации. Для создания класса в Питоне необходимо написать инструкцию , а затем выбрать имя. В простейшем случае, класс выглядит так:

Для именования классов в Python обычно используют стиль «camel case», где первая буква – заглавная.

Конструктор

Метод, который вызывается при создании объектов, в ООП зовётся конструктором. Он нужен для объектов, которые изначально должны иметь какие-то значение. Например, пустые экземпляры класса «Студент» бессмысленны, и желательно иметь хотя бы минимальный обозначенный набор вроде имени, фамилии и группы.

В качестве Питоновского конструктора выступает метод

Атрибуты класса

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

Поля могут быть статическими и динамическими:

  • Статические поля (поля класса) можно использовать без создания объекта. А значит, конструктор вам не нужен.
  • Динамические поля (поля объекта) задаются с помощью конструктора, и тут уже, как вы видели, экземпляр нужно создать, а полям присвоить значения.

️ Обратите внимание – статический и динамический атрибут может иметь одно и то же имя:

Методы класса

Метод – это функция класса.

Например, у всех научно-фантастических космических кораблей есть бортовое оружие. И оно может стрелять.

Что такое self?

Аналог этого ключевого слова в других языках – слово . – это всего лишь ссылка на текущий экземпляр класса.

Отличный пример с котофеями:

  1. Все котики умеют мурлыкать;
  2. Эта способность реализована в классе , как метод ;
  3. Вы хотите, чтобы ваш кот по имени Пушок помурчал;
  4. Если сделать так: , то мурлыкать начнут все коты во Вселенной;
  5. Но так как вам нужен один конкретный кот, то нужно вызвать метод иначе: ;
  6. Сделано. Пушок мурлыкает.

Уровни доступа атрибутов и методов

В Питоне не существует квалификаторов доступа к полям класса. Отсутствие аналогов связки public/private/protected можно рассматривать как упущение со стороны принципа инкапсуляции.

Декораторы

Декоратор – это функция-обёртка. В неё можно завернуть другой метод, и, тем самым, изменить его функциональность, не меняя код.

Что такое ООП

Возникло как результат развития процедурного программирования. Основой объектно-ориентированных языков являются такие принципы, как:

  • инкапсуляция;
  • наследование;
  • полиморфизм.

Некоторые принципы, которые были изначально заложены в первые ООЯ, подверглись существенному изменению.

Примеры объектно-ориентированных языков:

  1. Pascal. С выходом Delphi 7 на официальном уровне стал называться Delphi. Основная область использования Object Pascal — написание прикладного ПО.
  2. C++ широко используется для разработки программного обеспечения, является одним из самых популярных языков. Применяется для создания ОС, прикладных программ, драйверов устройств, приложений, серверов, игр.
  3. Java — транслируется в байт-код, обрабатывается виртуальной машиной Java. Преимуществом такого способа выполнения является независимость от операционной системой и оборудования. Существующие семейства: Standard Edition, Enterprise Edition, Micro Edition, Card.
  4. JavaScript применяется в качестве языка сценариев для web-страниц. Синтаксис во многом напоминает Си и Java. Является реализацией Ecmascript. Сам Ecmascript используется в качестве основы для построения других скриптовых языков, таких как JScript, ActionScript.
  5. Objective-C построен на основе языка Си, а сам код Си понятен компилятору Objective-C.
  6. Perl — высокоуровневый интерпретируемый динамический язык общего назначения. Имеет богатые возможности для работы с текстом, изначально разработан именно для манипуляций с текстом. Сейчас используется в системном администрировании, разработке, сетевом программировании, биоинформатике и т. д.
  7. PHP. Аббревиатура переводится как препроцессор гипертекста. Применяется для разработки веб-приложений, в частности серверной части. С его помощью можно создавать gui-приложения с помощью пакетов PHP-GTK, PHP-Qt, WinBinder.
  8. Python — язык общего назначения, ориентирован на повышение производительности разработчика и читаемость кода. Был разработан проект Cython, с помощью которого осуществляется трансляция программ, написанных на Python в код на языке Си.

Инкапсуляция в Java

Инкапсуляция — принцип, согласно которому атрибуты объекта заключаются в этот объект. Это задает для атрибутов контекст. Это также позволяет программисту ограничить доступ к атрибутам, чтобы они изменялись и использовались только через методы, которые программист собирается применять:

// Эта переменная не инкапсулирована.
// Поэтому в ней отсутствует какой-то контекст.
String name;
// БАЗОВАЯ ИНКАПСУЛЯЦИЯ
// Эти переменные и методы инкапсулированы в классе Dog. Они являются его членами.
class Dog {
    String name;
    int age;
    void bark() {
        System.out.println("Bark!");
    }
    void rename(String newName) {
        name = newName;
    }
}
// МОДИФИКАТОРЫ ДОСТУПА
// Приведенные выше члены доступны для любого другого
// класса. Чтобы определить доступы, используются модификаторы доступа:
// - default: Если модификаторы доступа отсутствуют, атрибут доступен
//    только для классов внутри одного пакета.
// - public: атрибут доступен из любого другого класса.
// - protected: То же самое, что и default, плюс он доступен для подклассов.
// - private: доступен только внутри объявленного класса.
class Dog {
    private String name;
    private int age;
    void bark() {
        System.out.println("Bark!");
    }
    void rename(String newName) {
        name = newName;
    }
    public String getName() {
        return name;
    }
    public void setAge(int newAge) {
        if(newAge > 0)
            age = newAge;
    }
    public int getAge() {
        return age;
    }
}

Полиморфизм

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

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

Если вернуться к программированию, то полиморфизм позволяет единообразно обращаться к объектам различных классов (обычно имеющих общего предка) — вещь, которую трудно переоценить. Ценность его тем выше, чем больше программа.

ООП — это принципы. Внутренние законы. Каждый из них нас в чем-то ограничивает, давая взамен большие преимущества, когда программа вырастает до больших размеров. Четыре принципа ООП — это как четыре ножки стула. Убери хотя бы одну, и вся система станет неустойчивой.

3 Что учить дальше?

Мы разобрали ценности и знаем к чему стоит стремиться, кроме того, мы поверхностно посмотрели на механизмы, которые предоставляет нам объектно-ориентированное программирование, не фокусируясь на каком-либо определенном языке

Однако, в программировании важна практика — посмотрите как описанные механизмы реализуются в вашем любимом языке и попробуйте реализовать небольшой проект.
Прочитайте про SOLID — постарайтесь заметить не только принципы, но также — проблемы и подходы к их решению.
Обратите внимание на модульное тестирование и TDD — это будет особенно полезно, если у вас не получается удачная архитектура. По моим наблюдениям, даже начинающий программист начинает писать более качественный код, если сначала подумает о том, как он этим кодом хочет пользоваться

Изучите библиотеку модульного тестирования вашего языка программирования и попробуйте писать тесты.
Посмотрите литературу о шаблонах проектирования , при этом я рекомендую не пытаться запомнить детали реализации паттернов, а ответить на вопросы «где я могу применить этот шаблон?», «какую пользу и вред я с этого получу?». Если это кажется вам тяжелым — посмотрите как с помощью паттернов можно улучшить качество кода .

3.1 Список использованных источников

  1. Рейтинг популярности языков программирования TIOBE. URL: https://tiobe.com/tiobe-index/
  2. SOLID принципы. Рефакторинг. URL: https://pro-prof.com/archives/1914
  3. Почему мне кажется, что студентов учат ООП неправильно. URL: https://habr.com/ru/post/345658/
  4. C++ Russia 2018: Фёдор Короткий, Память – идеальная абстракция. URL: https://vk.com/wall-105242702_701
  5. Мейер Б. Объектно-ориентированное конструирование программных систем. М.: Издательско-торговый дом «Русская Редакция», «Интернет-университет информационных технологий», 2005. 1232 с.: ил.
  6. Мартин Р. Чистый код. Создание, анализ и рефакторинг. Библиотека программиста. – СПб.: Питер, 2014. – 464 с.
  7. Джейсон Мак-Колм Смит Элементарные шаблоны проектирования : Пер. с англ. — М. : ООО “И.Д. Вильямс”, 2013. — 304 с.
  8. Диаграммы классов UML. URL: https://pro-prof.com/archives/3212
  9. Юнит-тестирование. Пример. Boost Unit Test. URL: https://pro-prof.com/archives/1549
  10. Э. Гамма Приемы объектно-ориентированного проектирования. Паттерны проектирования / Э. Гамма, Р. Хелм, Р. Джонсон, Д. Влиссидес. – СПб.: Питер, 2009. – 366 с.

Понятие «объект» в ООП

Сущность в адресном пространстве вычислительной системы, появляющаяся при создании экземпляра класса (например, после запуска результатов компиляции и связывания исходного кода на выполнение).

Объект — это появляющийся при создании экземпляра класса набор свойств и их значений в памяти,  на которые можно сослаться с помощью идентификатора:

  • каждое свойство состоит из имени и значения, ассоциированного с этим именем;
  • значением свойства может быть функция, которую можно назвать методом объекта. 

Свойства объекта в JavaScript

В JavaScript объект имеет свойства, ассоциированные с ним. Свойство объекта:

  • можно понимать как переменную, закрепленную за объектом;
  • определяют характеристики объекта.

Получение доступа к свойству объекта:

JavaScript

objectName.propertyName
// или
objectName

1
2
3

objectName.propertyName

// или

objectName»propertyName»

Примеры:

JavaScript

var myCar = new Object(); // создание объекта с помощью конструктора
myCar.make = «Ford»;
myCar.model = «Mustang»;
myCar.year = 1969;

// или
myCar = «Ford»;
myCar = «Mustang»;
myCar = 1969;

1
2
3
4
5
6
7
8
9

varmyCar=newObject();// создание объекта с помощью конструктора

myCar.make=»Ford»;

myCar.model=»Mustang»;

myCar.year=1969;

 
// или

myCar»make»=»Ford»;

myCar»model»=»Mustang»;

myCar»year»=1969;

Имена свойств объекта могут быть строками JavaScript, или тем, что может быть сконвертировано в строку, включая пустую строку. Как бы то ни было, доступ к любому имени свойства, которое содержит невалидный JavaScript идентификатор (например, имя свойства содержит в себе пробел и тире или начинается с цифры), может быть получен с использованием квадратных скобок. Этот способ записи также полезен, когда имена свойств должны быть динамически определены (когда имя свойства не определено до момента исполнения).

Примеры

JavaScript

var myObj = new Object(),
str = «myString»,
rand = Math.random(),
obj = new Object();

myObj.type = «Dot syntax»;
myObj = «String with space»;
myObj = «String value»;
myObj = «Random Number»;
myObj = «Object»;
myObj = «Even an empty string»;

console.log(myObj);

1
2
3
4
5
6
7
8
9
10
11
12
13

varmyObj=newObject(),

str=»myString»,

rand=Math.random(),

obj=newObject();

myObj.type=»Dot syntax»;

myObj»date created»=»String with space»;

myObjstr=»String value»;

myObjrand=»Random Number»;

myObjobj=»Object»;

myObj»»=»Even an empty string»;

console.log(myObj);

Обратите внимание, что все ключи с квадратными скобками преобразуются в тип String, поскольку объекты в JavaScript могут иметь в качестве ключа только тип String. Например, в приведенном выше коде, когда ключ obj добавляется в myObj, JavaScript вызывает метод obj.toString () и использует эту результирующую строку в качестве нового ключа

Аналогия

Можно представить объекты отделами компании. В большинстве организаций сотрудники не работают один день с кадрами, на следующий начисляя зарплату, а затем неделю занимаясь розничной торговлей. У каждого отдела есть свой персонал с четко возложенными на него обязанностями. Есть и собственные данные: показатели заработной платы, продаж, учет сотрудников и т. д. Люди в отделах работают со своей информацией. Разделение компании, таким образом, облегчает контроль за ее деятельностью и поддерживает целостность данных. Бухгалтерия отвечает за платежные ведомости. Если необходимо знать общую сумму заработной платы, выплачиваемой в южном филиале в июле, не нужно рыться в архиве. Достаточно направить записку ответственному лицу, подождать, пока этот человек получит доступ к данным и отправит ответ с требуемой информацией. Это гарантирует соответствие регламенту и отсутствие постороннего вмешательства. Таким же образом объект в ООП обеспечивает организацию приложения.

Следует помнить, что ориентация на объекты не касается подробностей работы программы. Большинство инструкций C++ соответствует операторам процедурных языков, таких как С. Действительно, функции-члены в C++ очень похожи на функции в С. Только более широкий контекст позволит установить, является ли инструкция процедурной или объектно-ориентированной.

Класс

Класс — это такой тип данных, который состоит из единого набора полей и методов.

Имеет внутренние и внешние интерфейсы для управления содержимым. При копировании через присваивание копируется интерфейс, но не данные. Разные виды взаимодействуют между собой посредством:

  • наследования;
  • ассоциации;
  • агрегации.

При наследовании дочерний класс наследует все свойства родителя, ассоциация подразумевает взаимодействие объектов. Когда объект одного класса входит в другой, это называется агрегацией. Но когда они еще зависят друг от друга по времени жизни, — это композиция.

Одной из главных характеристик является область видимости. Понятие по-разному определяется разными ЯП.

В Object Pascal описывается следующим образом:

ClassName = class(SuperClass)

private

{ использование элементов ограничивается только пределами модуля }

{ здесь указываются поля }

strict private

{ спецификатор доступа стал доступным с выходом Delphi 2007, обозначает то же, что и private }

protected

{ элементы могут использоваться внутри ClassName или при наследовании }

public

{ }

published

{ элементы доступны всем, они отображаются в Object Inspector’e }

end;

Здесь SuperClass — предок, от которого происходит наследование.

Для C++ создание выглядит так:

class MyClass: public Parent

{

public:

MyClass(); // конструктор

~MyClass(); // деструктор

protected:

private:

};

В этом примере Parent является предком, если таковой имеется. Спецификаторы private, public, protected обозначают то же самое, что в предыдущем примере на Паскале. Также мы видим конструктор, деструктор, доступные для любой части программы. У C++ все элементы по умолчанию являются private, соответственно, это можно не указывать.

Принцип подстановки Барбары Лисков (LSP)

Соответствует букве L акронима SOLID. Согласно этому принципу подтипы должны быть заменяемыми для супертипа. Другими словами, методы или функции, работающие с суперклассом, должны иметь возможность без проблем работать также и с его подклассами.

EPAM Data Quality Hiring Weeks

12–25 апреля, Онлайн, Беcплатно

tproger.ru

События и курсы на tproger.ru

LSP тесно связан с принципом единственной ответственности и принципом разделения интерфейса.

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

Ниже приведён пример такого кода на Java:

Функция провоцирует неявную ошибку при работе с экземпляром класса , потому что позволяет устанавливать отличные друг от друга значения ширины и высоты. Согласно принципу LSP, функции, использующие ссылки на базовые классы, должны иметь возможность использовать объекты производных классов, не зная об этом. Поэтому для корректной работы функция должна проверять, является ли передаваемый объект экземпляром класса Square, и в этом случае не позволять установить разные значения ширины и высоты. Отсюда идёт нарушение принципа.

Курс по теме SOLID Principles of Object-Oriented Design.

Разные правила, связанные с перерасходомDifferent overdraft rules

Последняя добавляемая функция позволяет взимать комиссию за превышение кредитного лимита вместо того, чтобы отклонять транзакцию.The last feature to add enables the to charge a fee for going over the credit limit instead of refusing the transaction.

Для этого можно, например, определить виртуальную функцию, в которой реализуется требуемое поведение.One technique is to define a virtual function where you implement the required behavior. Класс выполняет рефакторинг метода , чтобы получить два метода.The class refactors the method into two methods. Новый метод выполняет указанное действие, когда при выводе средств баланс получает значение ниже определенного минимума.The new method does the specified action when the withdrawal takes the balance below the minimum. Существующий метод имеет следующий код:The existing method has the following code:

Замените его следующим кодом.Replace it with the following code:

Добавленный метод предполагает, что его можно вызывать только из производных классов.The added method is , which means that it can be called only from derived classes. Это объявление предотвращает вызов метода другими клиентами.That declaration prevents other clients from calling the method. А ключевое слово означает, что производные классы могут изменять поведение.It’s also so that derived classes can change the behavior. Тип возвращаемого значения — .The return type is a . Аннотация указывает, что метод может возвращать .The annotation indicates that the method may return . Добавьте следующую реализацию в , чтобы списывать комиссию при превышении лимита на вывод средств.Add the following implementation in the to charge a fee when the withdrawal limit is exceeded:

В этом случае переопределение возвращает транзакцию с комиссией.The override returns a fee transaction when the account is overdrawn. Если при выводе средств лимит не превышен, метод возвращает транзакцию .If the withdrawal doesn’t go over the limit, the method returns a transaction. Это означает, что комиссия не взимается.That indicates there’s no fee. Чтобы проверить эти изменения, добавьте следующий код в метод в классе :Test these changes by adding the following code to your method in the class:

Запустите программу и проверьте результаты.Run the program, and check the results.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector