Подробный взгляд на "четырех китов" ООП

Здравствуйте.
Наверно многие из вас знакомы с такими основополагающими понятиями ОО подхода, как Инкапсуляция, Полиморфизм, Наследование и Абстрагированние. Уверен что любая статья на эту тему многим покажется скучной и устаревшей, но судя по статьям, заполнившим интернет, делаю вывод что ничего кроме сухого копирования материала они не включают. Хотелось бы ответить эти важные грани ОО подхода с практической стороны.
Абстрагированние
Хотелось бы сразу отметить что каждый из этих механизмов отвечает за решение различных задач. Абстрагированние отвечает за упрощение понимания предметной области, то есть то, что мы моделируем в нашей программе. Писали ли вы когда нибудь на партах в школе целые чаты? Думаю хотя бы видели подобное. Представим что мы хотим написать программу, которая избавит школу от вандалов, и переместит столь необычный способ общения в электронную среду школы - компьютерный класс! Предметной областью здесь будет являться своеобразный чат, который нам необходимо изучить и реализовать программно. Для этого нам обязательно надо избавиться от всего ненужного. Какие объекты должны присутствовать в электронном чате? Проведем ассоциации с предметной областью:
конкретная запись на парте - сообщение;
имя человека, подписавшегося под надписью на парте - автор сообщения;
столбик на парте, содержащий сообщения, связанные одной темой - комната чата, или даже лучше, список сообщений.
И так начало положено, теперь можно приступить к абстрагированнию.
Абстрагированние это выделение наиболее важного для решения задачи из всей совокупности. Так, при реализации сообщения, важно ли нам какой ручкой оно было написано, или какой нажим был на парту при написании? Стоит ли включать в класс Сообщение такие свойства как: положение сообщения, скорость записи, площадь используемой части парты; или достаточно одного свойства - текст сообщения? При написани классов, важно отсеить ненужное и оставить только важное (абстрагироваться от шелухи). Как это правильно сделать? Попробуйте начать с осмысления поставленной перед программой задачи, все что по вашему мнению для решения задачи вам не понадобится, можно смело опускать, но нужно помнить - задача должна быть поставлена правильно - иначе абстрагированние только повредит. Если бы в нашем примере было важно сохранить такие особенности предметной области, как цвет пасты, можно было бы добавить в класс Сообщение такое свойство, как - цвет текста.
Инкапсуляция
Используется для упрощения программы и возможности дополнять классы без серьезных изменений.
Представим что мы уже написали часть нашего школьного чата, и вдруг нам понадобилось знать дату написания каждого сообщения, а в нашем классе Сообщение есть только свойства: текст и цвет текста. Думаю многие усмехнуться и подумают - да что тут сложного, написал дополнительное свойство в класс и все дела - а ведь именно в этом прелесть инкапсуляции. Если говорить конкретно, то это свойство системы позволяет скрывать одни данные от других. Другими словами пользоваться своими данными может только объект, другие объекты могут только взаимодействовать с ним, а не изменять работать с его данными напрямую. Нам достаточно перенести свойства класса в приватный список, и после чего добавлять или удалять из этого списка все что угодно, при этом другие объекты даже этого не заметят, потому что изначально им был закрыт доступ к этим данным. Приведу другой пример. Представьте что у вас есть класс, который отвечает за чтение данных из файла построчно. Этот класс имеет внутренний указатель на текущую строку и при вызове метода - получить строку - из файла считывается строка, на которую указывает указатель. Есть также методы: следующая строка и предыдущая строка - которые смещают указатель соответственно вперед и назад при этом проверяю не достигнут ли конец или начало файла. В этом классе свойство - Текущая строка - естественно должно быть защищенным, а за его изменение должены отвечать только методы самого класса, иначе любой объект сможет поменять указатель строки на произвольное значение (на пример -1), что приведет к ошибке. С другой стороны если вам понадобится усовершенствовать ваш класс, заменив свойство Текущая строка на свойство Текущее предложение, вам достаточно будет изменить закрытое свойство и код в соответствующих методах, а внешние файлы даже не заметят изменений, так как изменения происходят внутри самого класса.

Наследование
Средство, позволяющее повторно использовать код и последовательно усложнять классы без копипасты.
Об этом средстве могу сказать очень мало. Дело в том что наследование довольно мощный и в то же время простой механизм. В общем смысле Наследование позволяет реализовать иерархическую структуру ОО модели типа - родитель, потомок. Как этот механизм поможет нам в работе над школьным проектом? Представьте что вам подфортило, и ваш директор заказал у вас (естественно не за бесплатно) полноценный чат с блекджеком и.. то есть с возможностью модерирования сообщений. Любой модератор это тот же пользователь, только с дополнительными возможностями, так нужно ли копипастеть для создания класса Модераторы, или лучше унаследовать все возможности класса Пользователь классом Модератор и добавить этому классу дополнительные возможности.
Другой пример приведу из области биологии. Гусеница превращается в бабочку при этом она приобретает дополнительные возможности, а некоторые из возможностей изменяются, чему в ООП есть эквивалентный механизм переопределения методов при наследовании.
Полиморфизм
На мой взгляд, самый сложный в понимании механизм ОО подхода. Позволяет повторно использовать код и не заботится о изучении используемых в программе классов, а знать только то, что они должны делать.
Давайте представим, что многие из ваших одноклассников готовы оптимизировать методы ваших классов, но что же будет, если они начнут изменять их семантику (имя метода, возвращаемое им значение и необходимые для работы аргументы)? Программа просто перестанет работать, и каждая оптимизация потребует от вас изменять остальной код, чтобы он мог работать с новым, оптимизированным методом класса.
Для решения этой проблемы вы говорите своим одноклассникам - изменяйте методы, но не изменяйте их имен, типа возвращаемых значений и аргументов! Другими словами вы позволяете изменять только внутренний код метода, а не его внешний вид. При этом такие изменения не требуют менять программу!
Приведем другой пример. У вас есть класс для работы с файлом, тот самый, что позволяет считывать строки из файла построчно. Он имеет те же методы: ПрочитатьТекущуюСтроку(): String, СледующаяСтрока(): Boolean, ПредыдущаяСтрока(): Boolean. Вы определили интерфейс класса, то есть семантику его методов. Предположим, что другая функция принимает объекты данного класса и считывает с их помощью все из файла. Эта функция знает интерфейс класса и успешного его использует:
function ПрочитатьФайл(Файл $file){
$str = '';
do{
$str .= $file->ПрочитатьТекущуюСтроку();
}while($file->СледующаяСтрока())
return $str;
}
Теперь вам вдруг понадобилось изменить реализацию метода ПрочитатьТекущуюСтроку. Чтобы это не привело к необходимости изменять код функции ПрочитатьФайл, вам нужно сохранить семантику метода, то есть ПрочитатьТекущуюСтроку(): String - функция сохраняет имя, ее аргументы, и тип возвращаемого значения. Теперь можно без опасения изменять код метода, при этом изменять функцию нам не придется. Удобно, правда?
Полиморфизм позволяет реализовывать функции, методы и классы так, чтобы при изменении их реализации, не приходилось изменять другой код.
Собственно, такая структура как Интерфейс, позволяет определить структуру класса и не заботится о его реализации.

URL: https://visavi.net/articles/386