C++ — Структурное программирование или ООП


Содержание

лабы по информатике, егэ

лабораторные работы и задачи по программированию и информатике, егэ по информатике

Объектно-ориентированное программирование (как расшифровывается ООП) – это, прежде всего, парадигма программирования.
Парадигма программирования определяет то, как программист видит выполнение программы.
Так, для парадигмы ООП характерно, что программист рассматривает программу в виде набора взаимодействующих объектов, в то время как, например, в функциональном программировании программа представляется в виде последовательности вычисления функций. Процедурное программирование или, как его еще правильно называют, классическое операциональное, подразумевает написание алгоритма для решения задачи; при этом ожидаемые свойства конечного результата не описываются и не указываются. Структурное программирование в основном придерживается тех же принципов, что и процедурное, лишь немного дополняя их полезными приемами.
Парадигмы непроцедурного программирования, к которым можно отнести объектно-ориентированную парадигму, имеют совершенно другие идеи.
Определение Гради Буча гласит: “Объектно-ориентированное программирование – это методология программирования, которая основана на представлении программы в виде совокупности объектов, каждый из которых является реализацией определенного класса (типа особого вида), а классы образуют иерархию на принципах наследуемости”.
Структурное и объектно-ориентированное программирование строятся на таком научном методе как декомпозиция — метод, который использует структуру задачи и позволяет разбить решение общей большой задачи на решение последовательности меньших задач. Декомпозиция ООП происходит не по алгоритмам, а по объектам, использующимся при решении задачи. Данная декомпозиция уменьшает размер программных систем благодаря повторному использованию общих механизмов. Известно, что системы визуального программирования или системы, построенные на принципах объектно-ориентированного программирования, являются более гибкими и легче эволюционируют со временем.

История развития ООП берет свое начало в конце 60-х годов. Первым объектно-ориентированным языком был язык программирования Simula, созданный в компьютерном центре в Норвегии. Язык предназначался для моделирования ситуаций реального мира. Особенностью Simula было то, что программа, написанная на языке, была организована по объектам программирования. Объекты имели инструкции, называемые методами, и данные, которые назывались переменными; методы и данные определяли поведение объекта. В процессе моделирования объект вел себя согласно своему стандартному поведению и, в случае необходимости, изменял данные для отражения влияния назначенного ему действия.

Сегодня существует достаточное количество объектно-ориентированных языков программирования, наиболее популярными из которых в настоящее время являются C++, Delphi, Java, Visual Basic, Flash. Но, кроме того, многие языки, которые принято причислять к процедурной парадигме, тоже обладают свойствами ООП, имея возможность работать с объектами. Так, объектно-ориентированное программирование в C — это большой раздел программирования на данном языке, то же самое касается ООП в python и многих других структурных языках.

Говоря об ООП, часто всплывает еще одно определение — визуальное программирование. Оно дополнительно предоставляет широкие возможности использования прототипов объектов, которые определяются как классы объектов.
События. Во многих средах визуального программирования реализована характеристика (помимо инкапсуляции, полиморфизма и наследования) объекта – событие. Событиями в объектно-ориентированном программировании называется возможность обработки так называемых сообщений (или событий), получаемых от операционной системы Windows или самой программы. Данный принцип характерен для всех компонентов среды, которые обрабатывают различные события, возникающие в процессе выполнения программы. По сути, событие — это некоторое действие, которое активизирует стандартную реакцию объекта. Событием может рассматриваться, например, щелчок по кнопке мыши, наведение курсора мыши на пункт меню, открытие вкладки и т.п. Очередность выполнения тех или иных действий определяется как раз таки событиями, возникающими в системе, и реакцией на них объектов.
Классы и объекты в ООП — различные понятия. Понятие класса в ООП – это тип данных (такой же как, например, Real или String), а объект – конкретный экземпляр класса (его копия), хранящийся в памяти компьютера как переменная соответствующего типа.
Класс является структурным типом данных. Класс включает описание полей данных, а также процедур и функций, которые работают с этими полями данных. Метод ООП – это и есть такие процедуры и функции применительно к классам.
Классы имеют поля (как тип данных запись — record), свойства, которые похожи на поля, но имеют дополнительные описатели, определяющие механизмы записи и считывания данных и методы — подпрограммы, которые направленны на изменение полей и свойств класса.

Основные принципы ООП

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

Принцип наследования ООП и подклассы

Абсолютно все объекты создаются на основе классов, при это они наследуют свойства и методы этих классов. В свою очередь классы могут создаваться на основе других классов (родителей), тогда такие классы называют подклассами (потомки). Подклассы наследуют все свойства и методы родительского класса. Кроме того для подкласса или класса-потомка можно определить новые, свои собственные, свойства и методы, а также изменять методы класса-родителя. Изменение свойств и методов родительского класса отслеживается в подклассах, созданных на основе этого класса, а также в объектах, созданных на основе подклассов. В этом и заключается наследование ООП.

Полиморфизм ООП

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

На сайте представлена частичная теория объектно-ориентированного программирования для начинающих и ООП примеры решения задач. ООП уроки сайта представляют собой подробные алгоритмы выполнения поставленной задачи. На основе выполнения данных лабораторных работ учащийся сможет в дальнейшем самостоятельно решать другие аналогичные задачи.
Желаем Вам легкого и интересного изучения объектно-ориентированного программирования!

Объектно-ориентированное программирование

Определение классов

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

Класс предназначен для описания некоторого типа объектов. То есть по сути класс является планом объекта. А объект представляет конкретное воплощение класса, его реализацию.

Класс может определять переменные и константы для хранения состояния объекта и функции для определения поведения объекта.

Например, определим простейший класс:

Для определения класса применяется ключевое слово class , после которого идет собственно название класса. В данном случае класс называется Person и представляет человека. После названия класса идет блок кода, который определяет тело класса.

После определения класса мы можем создавать его переменные:

Но данный класс мало что делает. Теперь изменим его:

Теперь класс Person имеет две переменных name и age, которые предназначены для хранения имени и возраста человека соответственно. Также класс определяет функцию move, которая выводит строку на консоль. Также стоит обратить внимание на модификатор доступа public: , который указывает, что идущие после него переменные и функции будут доступны извне, из внешнего кода.

Затем в функции main создается один объект класса Person. Через точку мы можем обратиться к его переменным и функциям. Например, через выражение

Можно передать значение переменной name. А с помощью выражения

Получить это значение в какую-нибуь переменную. Ну и также мы можем вызывать функции у объекта:

Консольный вывод данной программы:

Указатели на объекты классов

На объекты классов, как и на объекты других типов, можно определять указатели. Затем через указатель можно обращаться к членам класса — переменным и методам. Однако если при обращении через обычную переменную используется символ точка, то для для обащения к членам класса через указатель применяется стрелка (->):

Изменения по указателю ptr в данном случае приведут к изменениям объекта person.

Урок №112. Введение в ООП

Обновл. 9 Июн 2020 |

В уроке №10 мы определили объект в C++ как часть памяти, которая используется для хранения значений. Объект с именем называется переменной.

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

Так что же тогда является объектно-ориентированным программированием? Для лучшего понимания воспользуемся аналогией. Оглянитесь вокруг — везде находятся объекты: книги, здания, еда и даже Вы. Объекты имеют два основных компонента:

Свойства (например: вес, цвет, размер, прочность, форма и т.д.).

Поведение, которое они могут проявлять (например: открывать что-либо, делать что-то и т.д.).

Свойства и поведение неотделимы друг от друга.

Объектно-ориентированное программирование (сокр. «ООП») предоставляет возможность создавать объекты, которые объединяют свойства и поведение в самостоятельный союз, который затем можно многоразово использовать. Это приводит к созданию следующего кода:

Так не только читабельнее, но и понятнее, кем является объект ( you — Вы) и какое поведение вызывается ( driveTo — поездка). Вместо того, чтобы сосредоточиться на написании функций, мы концентрируемся на определении объектов, которые имеют чёткий набор поведений. Вот почему эта парадигма называется «объектно-ориентированной».

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

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

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

Обратите внимание, термин «объект» перегружен, он имеет несколько значений, что может вызывать некоторую путаницу. В традиционном программировании, «объект» — это часть памяти для хранения значений. В объектно-ориентированном программировании, «объект» — это тот же объект, что и в традиционном программировании, но который соединяет в себе как свойства, так и способы поведения. С этого момента, мы будем использовать термин «объект» в объектно-ориентированном смысле.

За репост +20 к карме и моя благодарность!

Глава №7. Итоговый тест

Комментариев: 16

«Объектно-ориентированное программирование (ООП) предоставляет возможность создавать объекты, которые соединяют свойства и поведения в самостоятельный союз, который затем можно многоразово использовать. Это приводит к созданию следующего кода: you.driveTo(work); «


( Это что универсальный код для всех случаев жизни ? )

» Так не только читабельнее, но и понятнее, кем является объект (you — вы) и какое поведение вызывается (driveTo — поездка). Вместо сосредоточения на написании функций, мы концентрируемся на определении объектов, которые имеют четкий набор поведений. Вот почему эта парадигма называется «объектно-ориентированной».

Эта фраза приведена вами в тексте . На каком языке она сформулирована ( для кого ?). И кто сможет понять что вы ей хотите сказать .
Прошу немножко по русски и для людей которые только осваивают само понятие ООП.

Еще раз спасибо за качественный перевод и оформление! У Вас прекрасный перевод, так все грамотно выглядит. Не могу нарадоваться, что нашла и подсела на Ваш сайт. Это лучшее, что я видела. Настолько все постепенно и по порядку, так грамотно составлены уроки, что, кажется, по другому невозможно все это объяснить и понять.
Дойдя до данной главы, сделала паузу для разнообразия на Страуструпа «Принципы и практика использования С++» — вот где каша и все в кучу((( Сначала покажут, через 5 страниц только объяснят. Это кошмар, хорошо, что я уже подготовлена Вашим сайтом. В начале книги совсем нет новой информации для меня (после Вашего сайта �� )
А здесь иногда происходит так: изучаешь урок, вроде все понятно, но мысль в голове — «к чему это? как это может использоваться?» — а в следующем или через 1-2 урока все встает на места и в новом материале все складывается. В этих уроках действительно все с нуля, подробно и без воды. Как вы откопали такое сокровище? Это просто диво дивное) Надеюсь, что у Вас получится перевести все уроки до конца!

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

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

Спасибо за ваш отзыв. Надеюсь хватит сил перевести уроки до конца ��

Этот урок по ООП создают ваши умельцы — которые или не хотят , или не могут донести ученикам то для чего нужен Class . Рассказывая об ООП нужно раскрыть не только содержимое ( привести программный код в примерах ), а объяснить людям механизм для чего нужен Class и как его использовать.
Из аналогии обычного программирования нужно сказать , что Class это то место где собираются подпрограммы — функции относящиеся к одной тематике — объекту, например Class Array — массивы данных ( подпрограммы обработки данных в массивах — вычисление среднего , сумм элементов, сортировки и т.п. ) .
Переменные в private: это фактически глобальные переменные которые объявляются для всех подпрограмм в классе ( они видны из любой подпрограммы данного класса ) — зти переменные в private являются параметрами класса .
Для того чтобы их настроить ( занести данные в эти переменные при конкретном обращении ) используетcя SET функция или функция с любым другим именем , которая заносит в переменные указанные в private конкретные значения – инициализирует параметры для одного конкретного объекта ( экземпляра класса).
Функционал get функций это обращение к каким либо подпрограммам обработчикам , которые производят любые вычисления и любые операции с использование данных в переменных private и возвращают результаты .
Так как данные в private видны из любой подпрограммы в данном классе Class , эти данные не нужно указывать каждый раз в параметрах при обращении к подпрограммам обработчикам , они уже имеются в параметрах – private.
За счет этого уменьшается объем кода программы.
Вот как то так , я бы сказал в видео по началу обучению ООП.

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

Посмотрим будет ли мое объяснеие более понятным чем ваше . Может кто нибудь прокомментирует.

Добрый день, Владимир. Я программирую на С++ уже порядком 10 лет. Не принимайте близко к сердцу, но ваше объяснение слишком сумбурно и готов поспорить, что ни один новичок вообще ничего не поймет из сказанного.

работаю программистом 2 года, пытаюсь учить своего младшего брата программированию по этим урокам, увидел ваш комментарий, для эксперимента сначала дал прочитать сам материал, потом ваш комментарий, он ничего не понял из того что вы написали, ваш коментарий это как «С++ за час»

Здравствуйте. Очень признателен за эту вводящую в ооп статью. Но всё же мне непонятно,то есть не могу постичь смысла в этом виде программирования. Чтобы объяснить что я имею в виду, и объяснить где я не понимаю, я приведу примеры. Я заранее искренне надеюсь на вашу помощь.
Итак, для меня понятно,что существует некий код,который понимает компилятор, код, который что делает, выполняет какую-то функцию. Достаточно знать каков код нужен для реализации чего то конкретного и программа работает. Это мне понятно. Не понятно ООП. Не понятно как объект,который мы создаем( к примеру кнопка, при нажатии которой, отправляется сообщение кому то) может что то делать,выполнять? Откуда компьютер знает как ему что то сделать? Мы просто пишем название объекта, пишем на английском что он делает и это всё работает? К примеру, я создаю объект,которой называю «кнопка» на английском, пишу на английском что она нажимается, и потом на этом же английском пишу просто банально что она отправляет сообщение кому то и всё? Так работает ооп? Будет она работать? Спасибо ещё раз за помощь.

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

Я обычно не оставляю комментарии, но данное изложение реально одно из самых лучших.

Так как я только изучаю программирование и плюсы мой первый язык, то уроки Дениса Маркова + данный учебник по C++, наверное, лучшая комбинация в мире))

Спасибо и Вам за комментарий и что читаете ��

Функциональное программирование или ООП?

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

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

Архитектуру придумали для упрощения сложного кода, а не для усложнения лёгкого.

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

Объектно-ориентированный подход

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

Но если просто возьмёте груду кода и просто перенесёте процедуры в классы, как я говорил на итенсиве, то не станете сразу объектно-ориентированным программистом. Это другой подход к компоновке кода. Целый отдельный образ жизни и мыслей.

Настоящее ООП нацелено на разделение обязанностей и сокрытие информации.

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

Цукерберг рекомендует:  Свой стартап 7 доводов за

Есть контроллер, управляющий всеми запчастями чёрными стрелками и подписанный на состояние кнопок по голубым проводам. Как этот агрегат работает?

Кнопка включения передаёт сообщение Меня нажали . Контроллер передаёт сообщение Включись нагревателю и Запустись на 10 секунд таймеру, подписываясь при этом на его сигналы. Через указанное время таймер уведомляет Я истёк и контроллер передаёт Выключись печке. А по сигналу с кнопки выключения контроллер передаёт сигналы Выключись нагревателю и Стоп таймеру.

Если вдруг надо будет перепрограммировать логику, то всего лишь доработаем «прошивку» главного контроллера.

А если нужно добавить термометр, дисплей и GSM-модуль для отправки SMS-уведомлений? Запросто подключаем их к контроллеру своими «родными» разъёмами и в обработчике события истечения от таймера мы после остановки печки отправляем SMS о готовности. Или автоматически фотографируем обед и постим в Instagram. Но суть здесь одна:

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

Это классический подход Model-View-Controller (MVC), часто используемый в оконных приложениях, где есть много кнопок, дисплеев и прочих элементов.

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

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

лишь бы это «что угодно» поддерживало указанный интерфейс:

Тогда просто создаём все устройства и закидываем их в контроллер:

И такой контроллер будет всех их включать и отключать по таймеру.

В хозяйстве это вещь весьма полезная. Даже продвинутые варианты таких контроллеров уже есть:

В такой можно включить даже электропилу, реализующую интерфейс ЕвроВилкаInterface .

А что если у нас в хозяйстве появилась бензопила? Она заводится особым образом и имеет свои методы:

Если у бензопилы нет кнопок вкл и выкл как у электропилы, то просто напишем адаптер:

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

В реальности нам пригодился бы скромный набор деталей:

И теперь одним махом включаем бензопилу в разъём контроллера:

Бензопила с Arduino-адаптером теперь ничем не отличается от нагревателя. Мощь полиморфизма :)

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


Приятно и удобно программировать специализированными ящиками, обменивающимися сообщениями.

Умело разделяя систему на объекты и продумывая сообщения между ними можно достичь нирваны в ООП. А влезая в это кривыми руками можно забыть о структуре и сделать месиво:

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

Функциональный подход

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

Пример: если Вы есть в соцсетях, то вас постоянно парсят маркетологи:

И получим результат:

Можно добавить город вначале:

и фильтры с группировками менять местами. Объекты с методами здесь никуда не впишешь.

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

Здесь идеально подходят ассоциативные массивы и другие примитивные структуры. Они не нагружают оперативку и процессор созданием тысяч и миллионов объектов для каждого элемента. Но что если фильтраций будет много? Дабы не копировать миллионные массивы снова и снова, удобнее передавать все значения по ссылке. Или сделать структуры в виде классов с полями, чтобы все значения хранились в памяти в одном экземпляре и передавались по указателю.

Чем это отличается от обычного процедурного подхода?

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

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

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

Умело разделяя расчёты на данные и функции можно достичь нирваны в ФП. А влезая в это кривыми руками можно забыть о структуре и сделать месиво.

Но как на ФП пишут сайты?

Поток вычислений

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

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

и теперь просто прогоняем массив наших товаров $items поштучно через эти операторы:

Если же работать с коллекциями вместо простых массивов, то можно реализовать и так:

Здесь у объектов класса CartItem скрипт считывает цену и количество. А как собирается результат? Потоком:

По этому примеру придумал скринкаст о подсчёте скидок. За ним ещё будет о написании многопоточного парсера, показывающий пользу неизменяемых данных при распараллеливании процессов. Кто ещё не подписался на вебинары, тот, как обычно, будет в пролёте.

Работа сайта

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

Теперь вызываем что-то вроде этого:

и видим сгенерированный ответ в виде массива:

или в виде объекта Response.

Вы это могли заметить во входном скрипте проекта web/app.php на Symfony:

в public/index.php в Laravel:

и в методе run() класса приложения yii\base\Application в Yii2:

Та же конвертация константы request в результат response , как и списка профилей в список сообществ.

И аналогично каждое действие контроллера и каждый middleware принимает Request и возвращает Response .

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

Вывод

Если рассматриваем проект как совокупность «ящиков», то удобно использовать ООП. Если как потоки преобразований данных, то удобнее ФП. Если это не подходит, то делаем гибрид или придумываем что-нибудь другое. Весьма забавно выглядят порой попытки спрограммировать «ящики» на функциональном подходе или реализовать гибкие преобразователи данных на ООП. И какой из этого главный вывод?

Чем больше парадигм и фреймворков знаешь (и умеешь), тем адекватнее можешь их сравнивать и выбирать.

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

Не пропускайте новые статьи, бонусы и мастер-классы:

Структурное программирование на с++ (Конспект лекций) (стр. 1 )

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4

ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ

имени П. А. СОЛОВЬЕВА

ПРОГРАММИРОВАНИЕ НА С++

Структурное программирование на C++

Общие сведения о языке C++. 4

Типы данных в C++. 5


Скалярные типы.. 5

Перечисляемый тип. 7

Определение типа пользователя. 8

Константы и переменные. 8

Объявление переменных и констант. 9

Именованные константы.. 9

Блоки. Область видимости переменных. 10

Преобразование типов в выражениях. 13

Оператор (операция) присваивания. 13

Ввод с клавиатуры.. 15

Вывод на дисплей. 15

Условный оператор. 15

Оператор выбора. 17

Операторы цикла. 18

Цикл с предусловием.. 18

Цикл с постусловием.. 19

Структура программы на C++. Функции. 21

Структурированные типы данных в C+

Символьные строки. 24

Передача параметров функции. Перегрузка функций. 26

Текстовые файлы в C++. Файловые потоки ввода-вывода. 28

Создание потока ввода-вывода. 29

Открытие и закрытие файла. 29

Обработка ошибок. 30

Чтение-запись символов в файл. 30

Ввод-вывод с преобразованием типов. 31

Чтение символьных строк из потока ввода. 33

Объявление указателей. 34

Операции над указателями. 34

Динамические переменные. 35

Указатели и массивы.. 37

Передача массивов в качестве параметров функции. 37

Связь указателей и массивов. Операции над указателями. 39

Динамические массивы.. 40

Работа со списочными структурами. 41

Линейный однонаправленный список. 41

Динамический стек. 44

Оценка алгоритмов. 46

Линейный поиск. 49

Двоичный поиск (дихотомия) 50

Общие сведения о языке C++

Прямым предшественником языка C++ является структурный язык программирования C, который был предложен Дэнисом Ритчи (Dennis Ritchie) в начале 70-х годов ХХ века для операционной системы Unix. Впервые детальное описание языка C было выполнено в 1978 году в книге Брайана Кернигана (Brian Kernighan) и Дэниса Ритчи, в 1998 году вышел первый стандарт языка. Особенность языка C состоит в том, что он соединил в себе все основные признаки структурного языка высокого уровня (блок, переменная, операторы присваивания, ветвления, цикла) с низкоуровневыми средствами манипулирования с битами, байтами, адресами. Таким образом, язык C представляет собой мощный инструмент, который позволяет программисту иметь практически полную власть над компьютером. Однако следствием этого является невозможность поддерживать жесткий контроль за корректностью действий, инициируемых программным кодом, поэтому ответственность за последствия выполняемых программой действий возлагается на программиста.

К концу 70-х годов прошлого века стала ощущаться ограниченность структурных языков и структурной технологии программирования при работе над крупными проектами. Одним из новых технологических направлений, призванных разрешить эту проблему, явилось объектно-ориентированное программирование. В 1979 году Бьерн Страуструп (Bjarne Stroustrup) предложил объектно-ориентированное расширение расширение языка C – язык программирования, который сначала получил название «C с классами» (класс – одно из базовых понятий объектно-ориентированного программирования), а с 1983 года стал называться C++. Страуструп в качестве прямых предшественников созданного им языка называет язык C и объектно-ориентированный язык программирования Simula67. Язык C++ — высокоуровневое расширение C, объектно-ориентированный язык высокого уровня, сохранивший все основные структурные и низкоуровневые возможности языка С. С одной стороны объектно-ориентированные средства существенно расширили возможности языка при реализации крупных программных проектов, с другой стороны наличие низкоуровневых средств сохраняет за программистом основную долю ответственности за корректность программного кода. Первый стандарт языка C++, который существенно упорядочил и улучшил язык, был принят в 1998 году.

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

Типы данных в C++

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

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


Скалярные типы

Основные скалярные типы C++:

double – вещественный с двойной точностью,

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

signed – знаковый (положительные и отрицательные значения),

unsigned –беззнаковый (только положительные значения).

Кроме того, в C++ определяется тип void – скалярный тип, множество значений которого пусто.

По умолчанию используются спецификаторы short и signed, т. е. отсутствие спецификатора длины соответствует значению «короткий», отсутствие спецификатора знака – значению «знаковый».

Особенность типа char в C++ состоит в двойственности трактовки. Значения этого типа могут рассматриваться как целые числа, над которыми могут выполняться соответствующие операции, или как байтовый код символов. Значения типа char (символьные константы) заключаются в апострофы: g’, ‘a; к типу char относятся и некоторые двухсимвольные значения (спецсимволы), например, ‘\n — переход к следующей строке.

Замечание: в C++ строковые константы заключаются в двойные кавычки, например, “stroka”. Поэтому ‘a’ – это символьное значение (литерал), а “a” – строковое значение, строка, состоящая из одного символа.

Размер типа int стандартом не определен и зависит от разрядности процессора и особенностей компилятора. Спецификатор short независимо от разрядности процессора устанавливает размер памяти для целого типа 2 байта, спецификатор long – 4 байта.

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

sizeof( ) – размер в байтах значения указанного типа,

sizeof – размер в байтах типа, соответствующего указанной переменной.

Не устанавливая конкретных значений объема памяти для типов данных, стандарт определяет следующие соотношения между ними:

Здесь season — имя определяемого перечисляемого типа. Значения перечисляемого типа считаются упорядоченными в соответствии с их последовательностью при определении типа. При этом каждому значению по умолчанию ставится в соответствие целое число – его порядковый номер в списке значений (нумерация значений начинается с нуля, а не с единицы).

При определении перечисляемого типа значения могут быть пронумерованы в явном виде. Например,

Почему в C++ нужно строить всю программу на ООП (длинный вопрос)?

Я программист на C++. Хочу понять, почему считается хорошим тоном строить всю программу на основе ООП. Приведу свой взгляд на ООП, и хочу, чтобы вы мне объяснили, где я не прав.

Пара слов о терминологии. Под «объектом» я понимаю «объект в смысле ООП», а не то, что понимается под объектов в стандарте C++ и на cppreference.com ( en.cppreference.com/w/cpp/language/object ).

Я прекрасно понимаю, зачем нужно программировать без goto. Зачем нужно разбивать код на функции. Но вот необходимости в повсеместном использовании ООП я не вижу. Все обоснования ООП кажутся мутными, сам ООП — хайпом.

Да, вы можете сказать, что ООП нужен, чтобы код выглядел красивее и чище, и чтоб его за мной было проще редактировать другому программисту. Отвечу так: «объяснить я и сам могу, я понять хочу» (c). Чем отличается разбиение на классы от обычного разбиения на функции, я не понимаю. И почему в первом случае другому программисту, работающем после меня, будет якобы проще.

ООП — это три кита: инкапсуляция, наследование и полиморфизм (при этом под полиморфизмом понимается динамический полиморфизм). Из этих трёх, как мне кажется, часто возникает потребность лишь в одном: инкапсуляция. И ещё в одном, не входящем в эту троицу: RAII. Что касается наследования и полиморфизма, то в них возникает потребность очень редко.

Но даже инкапсуляция и RAII, на мой взгляд нужны лишь там, где они нужны. Скажем, владеем мы каким-то ресурсом — файловым дескриптором или ещё чем-нибудь — нужен RAII. Или есть некие данные, к которым мы хотим предоставить некий интерфейс (возможно, гарантирующий сохранение неких инвариантов этих данных) и запретить их менять напрямую — нужна инкапсуляция (то есть в C++ это будет выражено классом с private и public функциями-членами). А зачем нужно строить всю программу на основе ООП — я не понимаю.

Что касается наследования и полиморфизма, то могу привести лишь несколько примеров, где они нужны. (При этом я считаю, что наследование нужно лишь в связке с полиморфизмом.) Первый — это библиотеки виджетов, такие как Qt. Объясню, зачем там нужно наследование и полиморфизм, на мой взгляд. Есть большой виджет, скажем, окно, на котором расположены другие маленькие виджеты, скажем, кнопки, чекбоксы и пр. Большой виджет хранит список маленьких виджетов. Допустим, большому виджету понадобилось нарисовать себя. Для этого нужно нарисовать все маленькие виджеты. А для этого он итерируется по ним по всем и вызывает у каждого функцию-член, скажем, draw. Проблема в том, что каждый из маленьких виджетов рисуется по-разному, то есть функция draw должна быть у каждого своя. Но при этом большой виджет должен неким образом одним циклом проитерироваться по всем и вот эту вот эту функцию draw, которая у каждого своя, каким-то образом вызвать. Как это сделать? Нужно сделать базовый класс и назвать его, скажем, QWidget (так он назван в Qt), объявить у него виртуальную функцию draw, унаследовать от QWidget остальные виджеты и переопределить у них этот draw. Большой виджет будет хранить в себе список QWidget’ов по указателю. Будет итерироваться по ним и virtual call’ом вызывать draw. Готово.

Вот только подобная ситуация в обычных программах (за пределами библиотек виджетов) возникает крайне редко. В данном случае наследование и полиморфизм оказались нужны, потому что мы имеем в данном месте указатель на «виджет вообще», мы не знаем в данном месте кода, какой это именно виджет, но нам нужно вызвать draw, который может быть разным в зависимости от типа виджета. Но подобное возникает крайне редко в программах за пределами библиотек виджетов. Где вообще может такое оказаться, что у нас есть указатель на сущность, и мы не знаем, что это конкретно такое?
Ладно, хорошо, такое может случится, но лишь иногда.

Ещё один пример, который я могу придумать: хранение AST (abstract syntax tree). Там, допустим, узлы, хранящие выражения, представлены типом Expression, от которого наследуются разные конкретные выражения, скажем, FunctionCall, Addition, Multiplication и так далее. И у Expression есть виртуальные функции для различных манипуляций с этим узлом. Но и это, опять-таки, лишь какой-то очень частный случай. И даже в нём можно придраться. Скажем, сделать выражение просто std::variant, хранящим разные варианты этого выражения. Тогда никакое наследование и полиморфизм не нужны. Когда нужно сделать какие-то манипуляции с выражением, делаем switch по типу выражения. Вы можете возразить, что тогда при добавлении нового типа выражения придётся всё менять. Ну да. В случае ООП тоже пришлось бы много чего менять. Вы скажете, что при добавлении нового типа выражения придётся всё перекомпилировать. Ну да. У типичных языков программирования типа C++ новые типы выражений добавляются крайне редко, ну придётся лишний раз каждый год пересобирать компилятор, ничего не случится. Вы скажете, что virtual call быстрее switch. Что ж, может быть оно и так, но тогда получается что в данном конкретном случае преимущество ООП всего лишь в скорости. Никаких философских обоснований тут нет.

Возьмём STL. STL’ные классы не имеют наследования и полиморфизма. Точнее, vector часто наследуется от vector_base, но это лишь деталь реализации, не видная пользователю vector’а. Да и само это наследование нельзя назвать идеоматическим, т. к. идеоматическое наследование, как я понимаю, подразумевает отношение «является», т. е. выходит, что «vector является vector_base», что за бред? От vector’а не рекомендуется наследоваться. Зато у STL’ных классов есть инкапсуляция и RAII, как раз то, что я хорошо понимаю. Я действительно понимаю, зачем vector’у инкапсуляция и RAII. Но вот без наследования и полиморфизма весь этот STL прекрасно работает, что, на мой взгляд, доказывает их ненужность.

На одном собеседовании меня попросили рассказать, как бы я стал писать тетрис. Как я бы разбил это приложение на классы. Подразумевается, что это графическое приложение. Фигурки цветные, красивые. Есть счётчик очков, всё как полагается. И я не смог ответить. Я не вижу тут необходимости в классах. Той редкой ситуации, как было с теми виджетами, когда у нас есть указатель непонятно на что, тут нет. Так что наследование и полиморфизм тут не нужны. Некие данные, у которых должен сохраняться некий инвариант, к которым хочется предоставить некий интерфейс, тут тоже отсутствуют. Значит, инкапсуляция тоже не нужна. Всё, не нужны тут объекты. Нужны функции. Нужны struct’ы. Мне подсказывают, что у приложения есть главное меню, в нём можно выбрать пункт «играть» и перейти к основному игровому полю. Ну да, окей, и что? Это всего лишь значит, что при нажатии на «играть» должна вызываться функция, которая будет отвечать за сам игровой процесс. А когда игра будет окончена, эта функция должна сделать return и вернуть управление в функцию, отвечающую за меню. Где тут объекты? Опять не нужны.

Цукерберг рекомендует:  AJAX с помощью jQuery. Руководство для начинающих

Мне нравится код ядра Linux. Никакого разделения программы на объекты там нет, и всё там окей, прекрасно без такого разделения живут. Правда, полиморфизм там всё же есть в каком-то виде. Например, там есть struct file (которая отвечает за открытый файл), который хранит в себе указатель на struct file_operations (я смотрел исходники Linux 4.11.6). struct file_operations — это своего рода таблица виртуальных функций. И она хранит в себе указатели на операции, которые можно делать с файлами. Своего рода виртуальные функции. И они действительно нужны. Потому что в ядре есть места, где мы работаем с файлом, и не знаем, что это именно за файл (это может быть файл на диске, конец пайпа или ещё что-нибудь), но в этот файл хочется записать. Как в том примере с виджетами. Видите? Полиморфизм есть, но он есть только там, где это нужно. И никакого «А давайте всю программу разобьём на классы, просто потому что так надо» тут нет. На мой взгляд, Linux устроен совершенно верно, именно так и нужно писать.

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

Вы можете ответить «Да, ты прав, ООП не нужно, точнее, нужно, но лишь иногда, писать всю программу на классах не надо». И может, даже аргументы какие-нибудь привести. Так вот, это не то, что мне сейчас надо. Я сейчас ищу работу. И для этого я хочу понять ООПшный стиль написания программ. Пусть даже он неправильный, скажем, с академической точки зрения. Но я хочу действительно его понять. Я хочу понять, как оно там сейчас делается в бизнесе. Это то, что мне сейчас на работе пригодится. Так что прошу писать только аргументы в пользу ООП, но не против. Я не хочу тут устраивать холивар на тему «Нужен ли ООП». Холивар на тему «А какое правильное определение ООП?» тоже прошу не устраивать. Ну там, «Что понимал под ООП Alan Kay?» и прочее. Будем понимать ООП в том смысле, в котором его обычно понимаю программисты на C++ сегодня, пусть даже по каким-то причинам это определение кому-то покажется неправильным.

Окей, что я хочу в качестве ответа. Идеальной была бы ссылка на какую-нибудь статью в блоге. Где бы объяснялось, зачем нужно делить программу на объекты. С примерами. Скажем, разбиралась бы какая-нибудь типичная задача. Тетрис, текстовый редактор. И объяснялось бы, как поделить её на классы. Причём, чтобы в качестве классов были не только виджеты. Зачем виджеты сделаны классами, допустим, я уже понял. И главное, чтобы объяснялось почему программу нужно написать именно так, на ООП, а не просто функциями, и почему именно таким способом разбить на классы, а не другим. Просто объяснения в стиле «Давайте напишем на ООП. Хряк, хряк, хряк. Получилось» не надо, хочется понять, зачем было сделано на ООП.

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

C++ — Структурное программирование или ООП?

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

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

Рассмотрим наиболее известные из технологий:

  • метод «северо-западного» угла (имеется в виду лист бумаги или экран дисплея). Программа пишется сразу от начала до конца, без использования каких-либо общих принципов;
  • технология структурного программирования, в ней предполагается придерживаться принципов модульности, нисходящего и пошагового проектирования программ, одновременного проектирования программ и структур данных.
  • технология объектного программирования: связана с использованием при проектировании программы понятий объектов и их классов.

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

В технологии ООП взаимоотношения данных и алгоритма имеют более регулярный характер: во-первых, класс (базовое понятие этой технологии) объединяет в себе данные (структурированная переменная) и методы (функции). Во-вторых, схема взаимодействия функций и данных принципиально иная. Метод (функция), вызываемый для одного объекта, как правило, не вызывает другую функцию непосредственно. Для начала он должен иметь доступ к другому объекту (создать, получить указатель, использовать внутренний объект в текущем и т.д.), после чего он уже может вызвать для него один из известных методов. Таким образом, структура программы определяется взаимодействием объектов различных классов между собой. Как правило, имеет место иерархия классов, а технология ООП иначе может быть названа как программирование «от класса к классу».

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

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

Олицетворением принципа модульности является библиотека стандартных функций. Она, как правило, обеспечивает полный набор параметризованных действий, используя общие структуры данных. Библиотеки представляют собой аналогичные Си-программы, независимо оттранслированные и помещенные в каталог библиотек.

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

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


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

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

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

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

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

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

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

Структурное программирование — модульное нисходящее пошаговое проектирование алгоритма и структур данных.

Понятия объекта, класса объектов. Центральными в ООП являются понятия класса и объекта. Образно говоря, ООП заключается не столько в использовании классов и объектов в программе, сколько в замене принципа программирования «от функции к функции» принципом программирования «от класса к классу».

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

Объект — структурированная переменная, содержащая всю информацию о некотором физическом предмете или реализуемом в программе понятии.

Класс — описание множества таких объектов и выполняемых над ними действий.

Это определение можно проиллюстрировать средствами классического Си:

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

  • класс определяется как структурированный тип данных ( struct );
  • объекты определяются как переменные класса;
  • возможно переопределение и использование стандартных операций языка, имеющих в качестве операндов объекты класса, в виде особых методов в этом классе.

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

Объект — переменная класса.

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

Объектно-ориентированное программирование (ООП) это совокупность понятий (класс, объект, инкапсуляция, полиморфизм, наследование), приемов их использования при проектировании программ, а Си++ — инструмент этой технологии.

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

Программирование «от класса к классу» включает в себя ряд новых понятий. Прежде всего, это — инкапсуляция данных, то есть логическое связывание данных с конкретной операцией. Инкапсуляция данных означает, что данные являются не глобальными — доступными всей программе, а локальными — доступными только малой ее части. Инкапсуляция автоматически подразумевает защиту данных. Для этого в структуре class используется спецификатор раздела private, содержащий данные и методы, доступные только для самого класса. Если данные и методы содержатся в разделе public, они доступны извне класса. Раздел protected содержит данные и методы, доступные из класса и любого его производного класса. Наличие последних позволяет говорить об иерархии классов, где есть классы — родители — шаблоны для создания классов — потомков. Объекты, полученные из описания класса, называют экземплярами этого класса.

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

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

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

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

Классы в C++. Инкапсуляция.


Новый тип данных — класс.

Целью введения концепции классов в С++ является предоставление программисту средств создания новых типов, которые настолько же удобны в использовании, как и встроенные типы. Тип является конкретным представлением некоторой концепции. Например, встроенный тип С++ float вместе с операциями + , — , * и т.д. является воплощением математической концепции вещественного числа. Класс — это определенный пользователем тип. Мы создаем новый тип для определения концепции, не выражаемой непосредственно встроенными типами. Например, мы могли бы ввести тип TrunkLine (междугородная линия) в программе, имеющей отношение к телефонии, тип Depositir (вкладчик) в программе управления банком или тип Pretator (хищник) в программе экологического моделирования.

Класс — фундаментальное понятие С++ и лежит в основе многих свойств С++. Класс предоставляет механизм для создания объектов. В классе отражены важнейшие концепции объектно-ориентированного программирования: инкапсуляция, наследование, полиморфизм.

С точки зрения синтаксиса класс в С++ — это структурированный тип, образованный на основе уже существующих типов.

В этом смысле класс является расширением понятия структуры. В простейшем случае класс можно определить с помощью конструкции:

где

  • тип_класса – одно из служебных слов class , struct , union ;
  • имя_класса – идентификатор;
  • список_членов_класса – определения и описания типизированных данных и принадлежащих классу функций.

Функции – это методы класса, определяющие операции над объектом.

Данные – это поля объекта, образующие его структуру. Значения полей определяет состояние объекта.

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

Для описания объекта класса (экземпляра класса) используется конструкция

В определяемые объекты входят данные, соответствующие членам-данным класса. Функции-члены класса позволяют обрабатывать данные конкретных объектов класса. Обращаться к данным объекта и вызывать функции для объекта можно двумя способами. Во-первых, с помощью «квалифицированных» имен:

Имя класса может быть опущено

класс «комплексное число»

Второй способ доступа использует указатель на объект

Доступность компонентов класса

В рассмотренных ранее примерах классов компоненты классов являются общедоступными. В любом месте программы, где «видно» определение класса, можно получить доступ к компонентам объекта класса. Тем самым не выполняется основной принцип абстракции данных – инкапсуляция (сокрытие) данных внутри объекта. Для изменения видимости компонент в определении класса можно использовать спецификаторы доступа: public , private , protected .

Общедоступные ( public ) компоненты доступны в любой части программы. Они могут использовать любой функцией как внутри класса, так и вне его. Доступ извне осуществляется через имя объекта:

Собственные ( private ) компоненты локализованы в классе и не доступны извне. Они могут использоваться функциями-членами данного класса и функциями-«друзьями» того класса, в котором они описаны.


Защищенные ( protected ) компоненты доступны внутри класса и в производных классах. Защищенные компоненты нужны только в случае построения иерархии классов. Они используются также, как и private-члены, но дополнительно могут использоваться функциями-членами и функциями-«друзьями» классов, производных от описанного класса.

Изменить статус доступа к компонентам класса можно и с помощью использования в определении класса ключевого слова class . В этом случае все компоненты класса по умолчанию являются собственными.

Вопрос 20. ООП. Отличие от процедурного программирования

Читайте также:

  1. Агроэкология. Агроэкосистема. Отличие агроэкосистем от природных экосистем.
  2. Акты применения права : понятие, виды, отличие от нормативного правового акта.
  3. Акция и облигация. Отличие
  4. Алгоритмизация и программирование. Технологии программирования.
  5. Аудит и аудиторская деятельность. Отличие аудита от ревизии.
  6. Билет№26. Императивные, функциональные и логические языки программирования.
  7. В отличие от других канальцев имеют более темную окраску
  8. В чем заключается существенное отличие между произвольным и непроизвольным действием?
  9. В чем отличие понятий территориальная зона и функциональная зона?
  10. Введение. Последовательная и параллельная модели программирования.
  11. ВНП и его структура. Отличие ВНП от ВВП.
  12. Возбуждение ненависти или вражды, а равно унижение человеческого достоинства. Отличие данного состава от нарушения равенства прав и свобод человека и гражданина.

Объектно-ориентированное программирование (ООП) стало чрезвычайно популярно в последнее время. Объектно-ориентированное программирование часто называют новой парадигмой программирования. Другие парадигмы программирования: директивное (языки типа Pascal или C), логическое (языки типа Prolog) и функциональное (языки типа Lisp) программирование. Действие в объектно-ориентированном программировании инициируется посред­ством передачи сообщений агенту (объекту), ответственному за действие. Сооб­щение содержит запрос на осуществление действия и сопровождается допол­нительной информацией (аргументами), необходимой для его выполнения. Получатель — это агент, которому посылается сообщение. Если он принимает сообщение, то на него автоматически возлагается ответственность за выполнение указанного действия. В качестве реакции на сообщение получатель запустит некоторый метод, чтобы удовлетворить принятый запрос. Скрытие информации является важным принципом и в традиционных язы­ках программирования. Тогда в чем пересылка сообщений отличается от обычного вызова процедуры? В обоих случаях имеется последовательность точно определенных действий, которые будут инициированы в ответ на запрос. Однако имеются два существенных отличия.

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

Второе отличие состоит в том, что интерпретация сообщения (а именно метод, вызываемый после приема сообщения) зависит от получателя и явля­ется различной для различных получателей. Фундаментальной концепцией в объектно-ориентированном программировании является понятие обязанности или ответственности за выполнение действия.

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

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

Вопрос21. Понятие класса и объекта.

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

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

Классы представляются в виде иерархической древовидной структуры, в которой более абстрактные располагаются в корне дерева, а более специализированные классы и в конечном итоге индивидуумы располагаются на его конце, в ветвях. Классы могут быть организованы в иерархическую структуру с наследованием свойств. Дочерний класс (или подкласс) наследует атрибуты родительского класса (или надкласса), расположенного выше в иерархическом дереве. Абстрактный родительский класс — это класс, не имеющий экземпляров.

Дата добавления: 2015-03-31 ; Просмотров: 4453 ; Нарушение авторских прав? ;

Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет

Объектно-ориентированное программирование

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

Любая программа, написанная на языке ООП, отражает в своих данных состояние физических предметов либо абстрактных понятий – объектов программирования, для работы, с которыми она предназначена.

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

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

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

Класс – это описание множества объектов программирования (объектов) и выполняемых над ними действий.

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

Основные понятия объектно-ориентированного программирования

Любая функция в программе представляет собой метод для объекта некоторого класса.

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

Вся программа в таком виде представляет собой объект некоторого класса с единственным методом run (выполнить).

Программирование «от класса к классу» включает в себя ряд новых понятий. Основными понятиями ООП являются

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

Внутри объекта коды и данные могут быть закрытыми или открытыми.

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

Открытые коды и данные, напротив, доступны для всех частей программы, в том числе и для других частей того же самого объекта.

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

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

Иначе говоря, новый класс наследует как данные старого класса, так и методы их обработки.

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

Пример наследования – определение структуры, отдельный член которой является ранее определенной структурой.

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

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

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

Например, нахождение абсолютной величины в языке Си требует трех разных функций с разными именами:

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

Процедурное против объектно-ориентированного?

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

Стиль решения задачи зависит от того, на сколько сложен будет алгоритм её решения. Если вы, к примеру, можете её решить выполнив одно действие потом другое, затем, если не получится сделать третье, то вы выполните четвёртое — это процедурный стиль или по-другому — процедурное программирование (ПП). Инструкции для решения задачи выполняются одна за другой, сверху вниз, иногда возникают изменения в их последовательности. Среди команд нельзя выделить приоритетные, для решения задачи они просто должны быть выполнены.

Решение задачи в объектно-ориентированном стиле, применяя объектно-ориентированное программирование (ООП), оказывается ближе к реальности. Сложные задачи — это стихия ООП. В решении задачи участвуют программные объекты и ответственность за решение делится между ними. Часто, в процессе можно найти некоторые паттерны, поэтому при решении задачи некоторый участок кода используется многократно. Результат достигается путём распределения ответственности между объектами программы и повторным использования промежуточных решений.


Для того, чтобы сравнить два стиля, мы рассмотрим конкретную задачу, и по ходу её анализа будем смотреть, как это реализуется в ООП и в ПП.

Это должен носить у сердца каждый программист

Пока вы ещё не наворотили много трудно-читаемого и понимаемого кода, запишите себе на видном месте два принципа. Без них может получится “чёпопало” в ваших программах.
Запишите себе — DRY и KISS.

DRY (Don’t Repeat Yourself) — Не Повторяйся.
KISS (Keep It Simple, Stupid) — Не Усложняй, Тупица.

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

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

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

Кто-то может спросить — а что собственно происходит? Какие такие паттерны? Обычные! Можно сказать, это образцы решения задач. Но не конкретные примеры, а схемы, которые отражают взаимоотношения внутри приложения, между классами и объектами. Примером такого паттерна можно привести широко использующийся при разработке сайтов паттерн MVC. Это архитектурный паттерн, он предписывает разделить приложение на части — пользовательский интерфейс, бизнес-логику и контроллеры (они обеспечивают дополнительную обработку данных, соединяя бизнесс-логику и интерфейс).

Не кидайтесь сразу в изучение паттернов, получите опыт ООП на простых задачах, чтобы хоть как-то представлять, что там к чему. И уже потом, тада када …, ныряйте в паттерны на здоровье.

Проведём мысленный эксперимент

Вот и настало наконец-то время, когда мы можем с вами без всяких сомнений окунуться в мир … сравнения. Сравним на конкретном примере ПП и ООП.
Перед вами поставлена задача создать сайт риэлторской конторы об имеющейся недвижимости для продажи. Для этого вам было сказано сделать пару веб-страниц. На каждой должна быть форма администратора для ввода данных и таблица для отчёта о квартирах и коттеджах.
Для квартир, будет показываться следующее:

  • Площадь
  • Количество комнат
  • Тип дома
  • Цена
  • Этаж
  • Наличие балкона

Для коттеджей практически тоже самое:

  • Площадь
  • Количество комнат
  • Тип дома
  • Цена
  • Количество этажей
  • Отопление
  • Приусадебный участок

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

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

Далее мы создадим еще два класса: Коттедж и Квартира, оба будут наследовать все характеристики и методы класса Недвижимость и расширять его уникальными уже для себя свойствами и методами.

Класс Квартира, будет включать:

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

Для класса Коттедж, будут выделены характеристики:

  • Количество этажей
  • Отопление
  • Приусадебный участок

Допустим, что мы уже написали программы как в стиле ПП, так и в стиле ООП. Теперь представим, что мы пустили их в свободное плавание, стали использовать их на практике. И, как всегда бывает с реальными программами, они чем-то не понравились заказчику, или ему захотелось большего. Рассмотрим несколько сценариев развития наших программ.

Сценарий 1

Например, ваше начальство заинтересовалось продажей складов. У таких объектов недвижимости имеются специфические характеристики, по сравнению с любой другой недвижимостью:

  • Высота потолков
  • Устройство пола
  • Электроснабжение

ПП: Для нового объекта учёта, полностью с “нуля” создаётся всё новое и функции и форма.
ООП: Мы просто создаём новый класс Склад, наследуя всё необходимое от класса Недвижимость. В классе Склад, нам нужно будет только создать новые характеристики и методы для обработки новых данных.

Сценарий 2

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

Сценарий 3

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

Сценарий 4

Обнаружился баг в передачи смс с ценой, странным образом вместо шести нулей на конце, остаётся только один.
Процедурное: Ааааааа! Всё успокоились. Идём и исправляем код относящийся к каждому объекту недвижимости.
ООП: Наливаем себе любимый напиток, вдыхаем его аромат, и со спокойствием удава исправляем код одного метода в классе Недвижимость.

Заключение

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

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

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

Всё, что вам нужно знать из ПП

Давайте разберёмся в начале в понятиях. Специфических слов в процедурном программировании не так уж и много: модуль, тип данных, функция, конструкция, переменная, константа. Слова на слуху, поэтому пробежимся не особо останавливаясь:

  • Модуль — это кусок программы, чаще всего занимающий целый файл, и представляющий собой набор программных объектов (тип данных, функция, конструкция, переменная, константа), относящихся к решению определённого круга задач. Например, существуют модули, работающие с графическими возможностями компьютера, другие занимаются отправкой почты и т.д.
  • Тип данных — это способ описания множества данных похожих друг на друга по своей структуре. Например, если вы хотите описать множество всех целых чисел со знаком, которые можно хранить, выдавая каждому по четыре байта, то для этого есть тип данных int.
  • Функция — законченный кусок программы (которому дано имя), решающий определённую подзадачу в вашей программе. Существуют встроенные функции, кроме них создаются новые для решения задачи. Встроенные функции часто связаны с элементарным вводом и выводом информации, преобразованием данных и т.д.
  • Конструкция — это специальная инструкция, изменяющая поток выполнения программы. Например: ветвления и циклы.
  • Переменная — реально существующий в программе представитель некоторого типа данных. Например: переменная, хранящая целое число, относится к типу int.
  • Константа — тоже самое, что и переменная, вот только значение в такой переменной не меняется.

Всё, что вам нужно знать из ООП

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

  • Класс — это прототип для создания похожих объектов, определяющий что будет в них храниться и какую функциональную нагрузку они будут нести. Данные и функции формулируются в понятиях, используемых для решения задачи. Обычно он создаётся в соответствии с некоторым паттерном, и сосуществуя в системе с другими классами должен находится с ними в слабой связи. Экземпляр класса иногда называют коротко — объект.
  • Данные — это полезная информация, характеризующая конкретного представителя данного класса, например: его цвет, размеры, форму и т.д. Их хранение осуществляется в переменных членах класса.
  • Методы — определяют функциональные возможности класса, а также выполняют служебную роль для данных класса. Реализуются в виде функций членов класса.
  • Параметры — специальные переменные, от которых зависит результат работы методов класса. Параметры появляются тогда, когда их данные нельзя передать через переменные члены класса. Например, в специальных методах, которые называются сеттеры (от слова “set” — установка), без параметров не обойтись, собственно именно через них данные попадают в экземпляр класса. Также данные могут попасть в объект через специальный метод конструктор — через его параметры.
  • Экземпляр — это конкретный представитель класса объектов, создающийся во время работы программы, с помощью конструктора (см. выше). Каждый экземпляр некоторого класса обладает одинаковым набором характеристик и поведением (набором методов). Отличием будет являться только разное значение этих характеристик.
  • Наследование — один из замечательных принципов ООП. Он описывает механизм выстраивания иерархии классов, позволяющий из одного класса создавать другой класс. Если бы его не было, представляете каким бы толстым оказался класс, в котором мы бы попытались описать множество всех компьютерных комплектующих? В результате, каждый экземпляр такого класса тащил бы за собой ненужный шлейф из характеристик, которые принадлежат другим железкам. Например, у процессора болталось бы без надобности поле, хранящее разрешение монитора по горизонтали и вертикали. Но, у нас-таки есть принцип наследования! Мы можем создать нечто абстрактное — компьютерную железяку, которая обладает общими характеристиками и поведением всех железяк. И на основе её создать множество классов, которые уже будут содержать более специфические характеристики и поведение. Мы можем продолжать плодить классы, пока у нас не получится специальный класс, который будет описывать центральный процессор и не содержать ничего лишнего. Однако, учтите, что бы вы не сделали с родительским классом, это отразится на всех его потомках в любом “колене”.
  • Полиморфизм — ооо, это ооочень полезный принцип. Его сразу можно и не заметить, но когда вы начнёте использовать интерфейсы, вот тогдааа. Он описывает возможность создавать функции с одинаковым именем, но разным набором инструкций.
  • Инкапсуляция — вот с этим намного сложнее. Просто не совсем ясно, зачем называть то, что и так очевидно. Этот принцип говорит, что класс — это единое целое, включающее и данные и методы, которые могут обладать разным уровнем доступа из внешних ресурсов. Какие-то элементы класса доступны только внутри самого класса, до каких-то можно добраться где угодно. Главное — это “всё внутри”.
Цукерберг рекомендует:  Диаграммы и графики на HTML5
Понравилась статья? Поделиться с друзьями:
Все языки программирования для начинающих