Объектно-Ориентированная Диалектика: Философские корни ООП
Введение
Все опытные программисты были начинающими разработчиками и все сталкивались, так или иначе, в университете или на собеседованиях, с необходимостью объяснить, что такое ООП, чем оно отличается от процедурного программирования и что означают уже каноничные и даже меметичные принципы абстракции, инкапсуляции, наследования и полиморфизма. По своему опыту и исходя из отзывов в интернете, чёткого представления об ООП и его принципах нет ни у студентов, ни у кандидатов, ни у собеседующих их специалистов. Это связано с тем, что вместо попытки разобраться просто-напросто заучиваются готовые постулаты без понимания, какую задачу данный подход программирования решает. Поэтому принципы этого метода оказываются в сознании специалиста висящими в воздухе, обособленными и несвязанными между собой, тогда как естественный ход обучения в любой области начинается с постановки проблематики: что нам нужно сделать и что нам для этого необходимо? При верной постановке задачи и при помощи диалектического метода окажется, что ООП - это целостная система, где одно цепляется за другое, что значительно облегчит понимание этой концепции и научит выводить эту методологию вместо механического заучивания её основных концепций.
Раз я пообещал выведение этой концепции вместо её разъяснения, то я так и сделаю, начав с философской базы. Но всё-таки нужно помнить, что и я, и читатель уже знают о существовании процедурного, объектно-ориентированного и функционального способов программирования, так что стопроцентно непредвзятого изобретения велосипеда не получится. Однако в данном случае я постараюсь не подбивать разворачиваемый анализ под желаемый результат, а использовать рассматриваемые подходы как ограничительные рамки этой логической цепочки.
TL;DR (если кратко)
Мы абстрагируем объект из общего потока данных. Выделяя необходимые для текущей задачи существенные черты, мы противопоставляем объект другим данным/объектам, т.е. абстрагируемся от остальных данных и сосредотачиваемся только на минимальном наборе характеристик, которые можно сгруппировать. Противопоставляем этот объект себе же, образуя наследственную иерархию из родительских и дочерних классов, реализуя тем самым переиспользование алгоритмов и данных, а, например, в С# и Java подтверждаем единство всех объектов по принадлежности к типу object. Это в свою очередь предполагает, что дочерние классы могут быть использованы вместо базового, так как они лишь уточняют и развивают сущность, а также объект может быть объявлен без знания его реализации в будущем, таким образом следуя принципу полиморфизма. Чтобы этот принцип было возможно реализовать, нам нужно разграничить внутреннее и внешнее, сущность классов и содержание объектов, а также определить форму их проявления. Для этого и происходит инкапсуляция сущностных данных и алгоритмов, делая объект устойчивым и закрытым для модификаций, определяя общее для иерархии объектов и отводя место для реализации сущности в ходе разработки, делая класс открытым для расширения.
Раздел 1. Лирика
Часть 1. …и целое!
В начале было слово. Нет. В начале была материя. Просто материя — и только. Но если есть материя, то есть и не-материя (если есть “х”, то есть и не-”х”). Но если мы исходим из того, что наш мир материален, то как в нём может существовать что-то помимо материи?
Это формально-логическое противоречие разрешается диалектическим методом — через что-то третье. Что-то, что сочетает в себе свойства обоих агентов противоречия. В данном случае мир состоит из чего-то, что является и материей, и не-материей. Согласно другой диалектической предпосылке — всеобъемлющей взаимосвязи — можно догадаться, что этим чем-то выступает обособленная часть материи, которую можно назвать… объектом! Он материален, но в то же время не является всей материей вообще, а лишь её самостоятельным элементом - частью от целого.
Часть и целое - диалектические категории. Самостоятельный элемент/часть называется неорганическим. Несамостоятельный, имеющий значение лишь как компонент системы, называется органическим. Но, как и другие категории, это разделение является относительным, так как самостоятельность и несамостоятельность также относительна. Например, любой неорганический объект является органическим в том плане, что он существует лишь под действием всеобщих законов физики и он испытывает влияние остальных объектов материи.
Часть 2. Процесс
Продолжим. Если есть объекты, то есть и не-объекты? Ага =) Это отсутствие объекта. Самим своим существованием объект уже содержит своё определение, которое является и собственным отрицанием. И этим отрицанием может быть другой объект, потому что он не является данным объектом, хотя и сохраняет единство с ним в том плане, что они оба материальны. Иначе говоря, мы обнаружили материальное существование отсутствия объекта!
Но есть один нюанс =) Что насчёт существования нематериальных объекта и не-объекта? =) Если мы заговорили о материальном, то должно быть и нематериальное. Если существуют материальные объекты и их отрицание как не-объекты, а именно, отсутствие материи какого-то конкретного объекта, то существует и нематериальное присутствие и отсутствие объекта, хотя бы в нашем разговоре! Однако в материальном мире не существует ничего нематериального. Объект уже является не-всей-материей, так что не выйдет ещё раз разделить его - получится снова часть и целое!
Выходит, парадокс: должен существовать нематериальный объект в материальном мире, что-то, что бы объединяло существование и отсутствие существования. Но только не для диалектической логики! Нам нужно, как и в прошлый раз, найти нечто третье. Черпаем вдохновение из нашей реальности. Или даже из этого самого текста! Обратите внимание на слово “существует”, которое прозвучало много раз в этом и прошлом абзацах. Это что-то нематериальное… Но вроде как это действие и оно имеет место в действительности… Это какой-то… процесс!
Процесс - это как раз то, что с помощью временной координаты объединяет все объекты и не-объекты. Вся материя движется от своего не-существования к своему существованию и обратно. Не существует ни одного объекта без процесса изменения во времени, не существует материи без движения.
Категорию движения можно вывести сразу из всеобщей материи (её ещё называют бытием), но я решил сделать это после категорий части и целого, чтобы как можно раньше ввести более знакомое понятие объекта для, как мне кажется, лучшего понимания.
Вы наверняка можете сказать, что к мысли о не-материи можно прийти через рассуждение “если существует материальный объект, то существует и нематериальный объект” и разговоры про не-объекты нам не нужны. Отнюдь. Нематериальный объект в своём экзистенциальном утверждении (простите за англицизм) является обыкновенным зеркальным отражением материального объекта. В таком понимании не-материи мы бы пришли к пустому тождеству “материя = не-материя”, тогда как отрицание отрицания объекта подчёркивает единство материи и движения, связывает понятие процесса с изменением объекта, позволяет нам понять, что вещам свойственно меняться и со временем переставать быть тождественными самим себе.
Часть 3. Процессы - в динамике, объекты - в статике
Итак, мы пришли к мысли об изменении. Это нематериальный объект в материальном мире =) Однако он опосредован материей - она является его носителем. Это означает, что наш мир - это совокупность процессов и объектов, которые претерпевают изменения и перестают быть самими собой. Эта ситуация очень напоминает корпускулярно-волновой дуализм. Если мы возьмём относительно большой временной промежуток, то мы можем и не заметить существования отдельных объектов - так они быстро рождаются и умирают. Мы будем видеть сам процесс, по какому закону он изменяет материю. А если мы будет смотреть на мир, близкий к статическому, то мы увидим объекты и практически не будем замечать процессов, действующих в нём.
Но всё-таки статический и динамический мир - понятия относительные. На каждом уровне “приближения” будут существовать процессы, для которых этот уровень “слишком медленный”, чтобы их проанализировать, и объекты, уловить существование которых невозможно ввиду слишком быстрого протекания процессов.
Часть 4. Момент
И снова, и снова применим приём диалектического разрешения противоречия через “третье”. Ведь если есть процессы, то есть и не-процессы, и если всё есть процесс, то не-процессы тоже должны быть своего рода процессами.
Как уже описывалось выше, процесс для человеческого познания существует на относительно скоротечных временных отрезках. Но в мире, близком к статическому, мы видим не сам процесс, а его момент - этап, промежуточный результат, некий итог и отправная точка одновременно. Это и есть наше “третье”: оно неразрывно связано с процессом и, тем не менее, является его противоположностью во времени.
Таким образом, мы возвращаемся обратно к понятию объекта как к моменту процесса. Не как к пустой статике, а как к подверженной изменениям материи, которая не была сотворена в готовом виде, а существовала в другом состоянии, и которая перейдёт в другую форму существования. Это уже не просто объект в вакууме - он обогащён вектором своего развития, так как является моментом процесса движения от простого к сложному.
Часть 5. Пограничное
Если есть момент (развития), то есть и не-момент (развития). Ну, догадаетесь сами, что это?) Очень похоже на то, что мы делали, когда “доставали” процесс. Это переход между одним моментом и другим. Что-то промежуточное, что-то пограничное, что само по себе также объект познания.
Часть 6. Внутреннее и внешнее
А что будет не-пограничным для пограничного?
Снова проворачиваем трюк с третьим. Если держать в уме, что пограничное - тоже объект (и даже особого рода момент!), то уже относительно него, обращаясь внутрь объекта, не-промежуточным будут выступать грани самого момента.
Пограничное разделяет объект и не-объект, как мы выяснили в прошлый раз. Но если мы говорим о самом объекте как моменте и ищем пограничное уже внутри него, то мы понимаем, что граница между объектом и не-объектом будет лежать между равенством самому себе, объекту, и равенством чему-то внешнему. Но мы не можем сравнивать этот момент с другим, внешним, — мы рассматриваем один-единственный. Вот и выходит: что-то внешнее должно быть тоже гранью этого же объекта, его бытием. Вот мы и пришли к мысли о внутреннем и внешнем бытии =)
Когда мы говорим о внутреннем, то имеем в виду ту часть объекта, которая изолирована от внешнего, составляет его сущность. А внешнее — это то, что не принадлежит сущности объекта, а это значит, что это нечто появляется при взаимодействии с другими объектами. Однако внешнее и внутреннее — это стороны одного объекта, и они неразрывно связаны. Не существует внешнего без внутреннего и внутреннего без внешнего. Внутреннее проявляется во внешнем. Также внешнее отражает внутреннее. Эти грани объекта ещё называют сущностью и явлением.
По мере объяснения одного за другим процессов, составляющих содержание исследуемого объекта, по мере выявления отдельных свойственных ему необходимых сторон и связей возникает потребность объединения всех этих знаний в единое целое, выведения их из единого принципа, представления всех необходимых сторон и связей в их естественной взаимообусловленности и взаимозависимости. Успешное решение этой задачи приводит к воспроизведению в сознании сущности исследуемых явлений, которая как раз и представляет собой совокупность всех необходимых, внутренних, устойчивых сторон и связей (законов), свойственных объекту, взятых в их естественной взаимозависимости. Явление же представляет собой проявление этих сторон и связей на поверхности через всю массу случайных отклонений. Необходимо прежде всего отметить, что эти категории неотделимы друг от друга. В. И. Ленин по этому поводу в «Философских тетрадях» писал: «... Тут тоже мы видим переход, перелив одного в другого: сущность является. Явление существенно...» Явление существенно в том смысле, что оно не бывает без сущности и всегда так или иначе обнаруживает, выражает ее.
Часть 7. Форма и содержание
Не перегрузились ещё? Не запутались?) Да? Нет!) В любой непонятной ситуации - отрицайте!
Отрицаем сущность и удерживаем её. Сущность - это самый глубокий момент и неизменная часть понятия, тогда как явление всегда будет разным, потому что оно зависит от внешнего объекта взаимодействия. Её отрицанием будет и сущность, и все второстепенные характеристики, которые могут меняться, т.е. всё содержание объекта. А если явление - это искажённая внешним воздействием сущность во вне-бытии, то, стало быть, существует и искажение само по себе, без взаимодействия, но всё ещё включающее сущность.
Мы уже установили, что отрицанием сущности будет содержание, текучее и нестабильное, которое и проявляет нам сущность в определённой форме, включающей не только грани сущности и её искажения в явлении при внешнем контакте, но и все те дополнительные преобразования, которые обеспечивает полное содержание объекта. Так мы получили ещё одну неразрывную пару: содержание-форма. Форма содержательна, содержание оформлено. Причём содержание не является исключительно внутренним моментом - оно включает и характеристики, направленные во вне. А форма отражает содержание, то есть также оформляет внутреннюю и внешнюю сторону предмета.
Сущность искажается в явлении не только через внешнее взаимодействие, но и через содержание. То есть сущность является уже в определённой форме в соответствии с конкретным содержанием, которая и вступает во взаимодействие. И уже во взаимодействии содержание может меняться, что будет явлением сущности в какой-то форме, но сама сущность остаётся постоянной.
Так как содержание включает в себя неизменную сущность и переменчивое её воплощение во взаимодействии, то форма для этого содержания также будет меняться, но особым образом. Содержание, с одной стороны, должно оставаться стабильным в соответствии с его сущностью, а с другой стороны, будет содержать случайные и временные характеристики и изменяться в явлении. А, соответственно, его форма должна не только отражать сущность, но и быть способной к трансформации, спровоцированной изменениями в содержании, и также способной трансформировать содержание при внешнем контакте. Но так как сущность должна оставаться неизменной в содержании, эта трансформация происходит по определённым правилам, по которым некоторые процессы, запущенные случайным внешним импульсом, отрабатывают с необходимостью. Этот свод правил, объединяющий всё содержание, всю взаимосвязь его компонентов, и обеспечивает форма, выступающая как структура содержания.
Форма является противоположностью содержания также в том плане, что содержание развивается, а форма выражает конкретный момент этого содержания. Не забываем, что форма - это отрицание явления, уникального для каждого случая взаимодействия. Это отрицание должно быть, наоборот, стабильным, потому как это есть выражение устойчивой структуры содержания в какой-то момент времени. Поэтому форма устойчива относительно развития содержания. Но так как, получается, форма не всегда точно выражает содержание, то в какой-то момент оно начинает сдерживать развитие, потому что внутренние связи уже не релевантны произошедшим изменениям. И трансформация формы происходит скачкообразно, революционно, когда в содержании накапливается достаточно изменений для перехода.
На этом я предлагаю закончить философствовать, потому что этого диалектического анализа нам достаточно, чтобы разобрать рассматриваемые парадигмы программирования.
Раздел 2. Физика
Часть 8. Не бросайте читать, это полезно для здоровья
СЮЮЮДААА!!! ПРОСТО КАМОН!!! Ну ты красава, что дочитал! А ведь это ещё не всё!
Мы не просто так обратились к диалектике. Она отражает то, как в действительности соотносятся объекты и процессы. А объектно-ориентированное программирование тем и ценно, что оно соединило предметную область с программным кодом, вычленив из сплошного потока данных объекты состояний, которые взаимодействуют между собой с помощью определённых операций для внешнего взаимодействия, и определив концепции изменения этих объектов в процессе разработки программного продукта.Принципы ООП так же неразрывно связаны между собой, как и их диалектическая основа, отражающая суть вещей в реальном мире. Не в полной мере, но к критике мы ещё вернёмся.
Часть 9. Данные - это материя
Как и в начале нашего философского анализа, определим пространство, которым оперирует программное обеспечение. Это данные. Вся суть софта - это хранение, вычисление данных и представление их в удобном для пользователя виде. Помните, как раньше назывались компьютеры? ЭВМ - электронно-вычислительная машина. Кстати говоря, эта аббревиатура до сих пор фигурирует в юридических документах, где нужно обозначить какую-то компьютерную технику =)
Часть 10. Абстракция
Но данные не обрабатываются вот так вот целиком, одним большим куском. Они разбиты на части, на *объекты*. Мы выделили часть и целое у всеобщей материи и получили понятие объекта. А здесь наша материя - это данные! Мы это делаем за счёт того, что противопоставляем части данных друг другу, абстрагируем части от целого по определённым характеристикам.
Нужно помнить, что вся материя (и данные!) образуют взаимосвязь, т.е. обладают общими чертами. Это фундаментальная основа диалектики. Но части данных, объекты, различны относительно определённого уровня абстракции, некоторых качеств. Например, автомобиль и Солнце относятся к классу материальных объектов: они имеют массу, температуру и т.д. Однако мы потому и разделяем понятия звёзд и автомобилей, что для познающего субъекта важны другие качества материи, которые проистекают из иных количественных характеристик той же массы и температуры, иных взаимосвязей и внутреннего устройства. То есть это наблюдатель определяет, по какому признаку ему классифицировать объекты - в зависимости от их места в разрабатываемой системе. И этот набор качеств должен однозначно определять объект и противопоставлять его другим объектам, причём этот набор не включает в себя всеобщие характеристики. Это будет избыточно: всем и так известно, что материи свойственно понятие массы, и для выработки понятия автомобиля этого будет недостаточно.
Это был принцип абстракции. Вот как нам его даёт Википедия в его технической детализации:
Абстра́кция в объектно-ориентированном программировании — это использование только тех характеристик объекта, которые с достаточной точностью представляют его в данной системе. Основная идея состоит в том, чтобы представить объект минимальным набором полей и методов и при этом с достаточной точностью для решаемой задачи.
Часть 11. Наследование
Как вы помните, следующее, что мы определили в философской части, это понятие процесса. Если абстракция обеспечивает противоположность объектов - моментов изменения - то наследование отвечает за единство данных через формирование иерархии. Обеспечить взаимосвязь можно и с помощью агрегации и композиции, однако это приёмы по чисто механическому объединению объектов, тогда как наследование сохраняет диалектическое единство и противоположность: к дочернему объекту можно обращаться, как к его родителю, но родительский объект не содержит в себе конкретизацию наследников. В объектно-ориентированных Java и C# все объекты наследуются от типа object - общий родительский тип для всех объектов. Тем самым все классы наследуют поля и методы object: они являются object, но они и не-object, так как содержат дополнительную детализацию.
В C#, например, есть своя внутренняя диалектика =) Он реализует концепцию ссылочных (reference) и значимых (value) типов, которые являются противоположностями относительно способа передачи данных по ссылке либо копированием значения целиком и использования стека или выделения памяти в “куче” (ОЗУ). Все reference-типы наследуются от object, а все value-типы - от специального типа ValueType. Однако сам ValueType также наследуется от object =) Просто он реализует специальное поведение, определённое в Intermediate Language (IL) и Common Language Runtime (CLR).
А вот и техническое описания принципа наследования:
Наследование (англ. inheritance) — концепция объектно-ориентированного программирования, согласно которой абстрактный тип данных может наследовать данные и функциональность некоторого существующего типа, способствуя повторному использованию компонентов программного обеспечения.
Часть 12. Полиморфизм
Мы помним, что каждый существующий объект - это момент процесса, промежуточный результат постоянного изменения. Моменты также выделяются в движении человеческого познания от абстрактного к конкретному применительно к исследованию какого-либо явления.Например, понятие “демократия” появилось в античности и в то время исчерпывало себя, не нуждалось в уточнении. Демократия означала, что источником власти является, например, городское население Рима, греческое народное собрание и т.д., что было противоположностью диктатуры - передачи власти в одни руки для более эффективного “кризисного менеджмента”. Со временем общество развивалось - развивалось и уточнялось понятие демократии. Благодаря открытиям классовой природы общества, происхождения государства и законам экономического развития стало возможным изучить суть демократии, классифицировав её для каждой общественно-экономической формации: рабовладельческая демократия (власть рабовладельческого класса), феодальная демократия (власть феодалов), буржуазная демократия (власть класса капиталистов).
Эти подтипы являются уточняющими: суть у них различная, но они не отменяют общих принципов “демократии вообще” - рассредоточение властных полномочий между всеми собственниками в данной экономической системе в рамках конкретного господствующего класса. Также и с диктатурой. Например, развитием “диктатуры вообще” для капитализма является фашизм - военная мобилизация нации под руководством узкого круга монополий для захвата ресурсов и рынков для защиты и укрупнения капитала.
Для объектов одного типа - в рамках одного качества - характерно сохранение сущности, которая является вовне при взаимодействии с внешним объектом. Однако явление это может быть разным по форме, потому что содержание объекта может отличаться в зависимости от реализации. Банальный пример: машина умеет ездить, но каждая машина делает это по-своему. Чтобы сказать “поехали”, нам не нужно описывать, какие именно действия нужно совершить двигателю и какие механизмы должны прийти в движение. Собственно, это и описывает принцип полиморфизма:
Полиморфизм – это свойство системы использовать объекты с одинаковым интерфейсом без информации о типе и внутренней структуре объекта.
Мы говорили о сущности и явлениях демократии и автомобиля, о том, что содержание с ходом развития меняется, а сущность остаётся одинаковой. Для автомобиля - это передвижение по земле, для демократии - рассредоточение источников власти. Если бы эта сущность изменилась, то это уже была бы не демократия, а диктатура, в форме ли абсолютной монархии или фашизма. Сущность понятия государства - классовое господство - нельзя изменить, она будет сохраняться во всех его реализациях, от которых будет зависеть та форма, в которой она проявляется. Но это не значит, что объект государства будет существовать вечно: государство может исчезнуть вместе с исчезновением его основы - классов.Как вы поняли, полиморфизм подразумевает наследование объектов (наш предыдущий пункт) от менее детализированной абстракции. И вы наверняка заметили, что в наших рассуждениях само собой начали проскальзывать предпосылки к нашему последнему из столпов ООП - инкапсуляции.
Часть 13. Инкапсуляция
Для обеспечения функционирования полиморфизма нам необходимо разграничение пары «сущности-явления» объекта (того, как сущность себя обнаруживает через явление) и «формы-содержания».
Несмотря на то, что сущность момента стабильна, она является в какой-то форме в зависимости от полного содержания конкретного объекта, которое включает не только сущность, но и побочные для неё стороны предмета. Если мы изучаем государство, то оно существует в какой-то конкретной ипостаси, например, феодального государства. Но сущность государства никак не изменилась (классовое господство), а содержание будет включать реализацию - и оно будет иным при сравнении с капиталистическим государством.
Сущность и содержание объекта - это данные и способы их обработки. Явление - это результат взаимодействия сущности, который представлен в определённой форме в зависимости от содержания. Если упрощать, то сущность по отношению к содержанию выставлена вовне и доступна для взаимодействия в определённой форме. Содержание же влияет на то, в какой именно форме сущность проявится при внешнем взаимодействии.
Поэтому для поддержания идеи конкретного объекта в развитии, в различных его реализациях, нам нужно разграничить стабильную сущность и текущее содержание. Переходя на язык программистов, реализация основных заявленных функций объекта может быть разной, но интерфейс, который и определяет функциональную сущность объекта, остаётся неизменным. Для этого и существует принцип инкапсуляции: воспользовавшись определёнными модификаторами доступа в языке программирования, произвести инкапсулирование стабильной сущности (данные, методы) в объект и выставление наружу этой сущности для взаимодействия без возможности её изменения.
Инкапсуляция (англ. encapsulation, от лат. in capsula) — в информатике размещение в одном компоненте данных и методов, которые с ними работают. В реализации большинства языков программирования (C++, C#, Java и другие), обеспечивает механизм сокрытия, позволяющий разграничивать доступ к различным частям компонента.
Возьмём пример с понятием Пользователь. Обычно (ну не обычно, это будет в нашем случае) пользователь подразумевает логин и пароль - минимальный набор, составляющий его сущность, которая проявляется определённым образом. Если бы у пользователя при внешнем взаимодействии забрали поля логина и пароля, либо изменили их напрямую в обход дочерней реализации пользователя “КриптоЮзер” с хранением пароля в виде шифра, который устанавливается определённой функций, то пользователь перестал бы быть пользователем. Сущностью является не то, какой логин и пароль установлен у пользователя, а само наличие полей логина и пароля. А вот значения полей и способ их определения - это содержание объекта.
Это как у конкретного государства нельзя изменить его сущность подавления и конкретное её исполнение, потому что не только у понятия “государство” есть собственная сущность, но и у понятия “буржуазное государство” тоже есть буржуазная сущность =), которая является расширением базовой через собственное содержание.
Если бы все поля были public, то объект не имел бы того смысла, какой вкладывался при его конструировании, ведь управление над объектом полностью передано вовне: он полностью лишён самостоятельности и стабильности, а значит, он не соответствует своему определению как устойчивому состоянию - он выступает как лишняя прослойка в потоке данных между другими объектами. Теряется смысл объектов как состояния данных, которые и являются преимуществом ООП по сравнению с предшествующими концепциями.
Часть 14. Пример
Подытожим. Давайте реализуем на языке С# пример с Автомобилем с параметрами мощности двигателя, массой и методом “Ехать”.
Красным выделим сущность, зелёным - содержание, синим - форму. Часть сущности вынесена, как очень часто происходит, в интерфейс. Содержание предполагает алгоритмическую реализацию сущности и оформляется в виде класса со своей структурой. Явлением будет вызов методов и результат, например, car.Drive(10), которое изменит положение автомобиля - Location.
Унаследуем от него Боевой вертолёт автомобиль, которому можно давать команду открыть огонь, от чего будет зависеть его скорость (ну извините, какие времена - такие и примеры).
Посмотрим, что здесь происходит. Сущность автомобиля в виде его параметров (EnginePower, Weight) и свойства перемещения (void Drive()) остаются неизменными. Содержание, конкретная реализация сущности, отличается. Содержание проявляется в определённой форме: класс имеет собственную структуру, сущность автомобиля оформлена в классы с разной реализацией. Классы можно сконструировать по разным паттернам, но имплементировать они будут один и тот же интерфейс. Или, например, оформить класс как partial. Это всё будут разные формы для разных содержаний одной и той же сущности.
Важное замечание! Выше мы рассматривали сущность класса Car. Но если мы рассматриваем сущность класса MilitaryCar, то к ней добавится и свойство IsFiring, потому что это часть этой реализации, которая тоже является своим собственным понятием, а значит и сущность у него тоже есть. То есть если бы мы удалили свойство IsFiring, то автомобиль перестал бы быть военным, но остался бы автомобилем. А если бы удалили метод Drive(), то это был бы не автомобиль вовсе. Как говорится, если бы у бабушки был пропеллер, то это бы был вертолёт…
Явление сущности - изменение координаты автомобиля (Location) - также имеет форму: вызов метода может быть сделан в синхронной форме, асинхронной (для данного примера - нет xD), метод может быть записан в Task и выполнен в мультипоточном режиме.
Свойство Location на самом деле является скорее методом, чем полем. В C# свойства - это поля с возможностью управления доступом к ним через методы get и set. Эквивалентом свойству было бы объявить отдельно private поле Location и методы GetLocation и SetLocation. Это значит, что обращение к свойству будет проходит через вызовы методов, что влечёт за собой специфику отслеживания исключений, синхронность и т.д., тогда как работа с обычными полями (установка/запись) происходит мгновенно. “Полеподобная” запись свойств может сбивать с толку, так что стоит помнить, что работа с ними означает работу с реализацией и вызовом методов.
Часть 15. Выводы
ВОТ для этого нам и нужны принципы ООП! Это происходит одновременно. Мы абстрагируем объект из общего потока данных. Выделяя необходимые для текущей задачи существенные черты, мы противопоставляем объект другим данным/объектам, т.е. абстрагируемся от остальных данных и сосредотачиваемся только на минимальном наборе характеристик, которые можно сгруппировать. Далее, мы противопоставляем этот объект себе же, образуя наследственную иерархию из родительских и дочерних классов, реализуя тем самым переиспользование алгоритмов и данных, подтверждаем единство всех объектов по принадлежности к типу object. Это в свою очередь предполагает (при следовании третьему правилу из SOLID), что дочерние классы могут быть использованы вместо базового, так как они лишь уточняют и развивают сущность, а также объект может быть объявлен без знания его реализации в будущем, таким образом следуя принципу полиморфизма. А чтобы этот принцип было возможно реализовать, нам нужно разграничить внутреннее и внешнее, сущность классов и содержание объектов, а также определить форму их проявления. Для этого и происходит инкапсуляция сущностных данных и алгоритмов, делая объект устойчивым и закрытым для модификаций, определяя общее для иерархии объектов и отводя место для реализации сущности в ходе разработки, делая класс открытым для расширения.
Если выкинуть хотя бы один принцип, то методология перестанет отражать действительное функционирование процессов. Нет абстракции - и вот мы оперируем сплошным потоком данных, к которому остальные принципы не применимы. Выкинем наследование - каждый объект превращается в лучшем случае в контейнер других объектов с полностью открытой структурой для хоть какой-то компенсации отсутствия эффективного механизма переиспользования кода, где полиморфизм не работает, а инкапсуляция не нужна. Отменим полиморфизм - и не понятно, на кой ляд мы проводили наследование, если все объекты имеют, по сути, в одностороннем порядке индивидуальную сущность, и нужно всегда знать, какая конкретная реализация будет в определённый момент. Если не будет инкапсуляции, то невозможно будет конструировать устойчивый объект, поддерживать разделение на интерфейс и реализацию и исполнять остальные принципы ООП.
Часть 16. Немного критики ООП
Надеюсь, вы поняли, почему это объектно-ориентированное программирование. Потому что оно оперирует состояниями развития понятий. Однако из того, что оно ориентировано на состояния, следует и недостаток - неориентированность на процессы. ООП требует предопределение состояний для запуска программы, но не рассматривает динамические процессы с масштабом, когда состояния настолько быстро меняются, что не удаётся (или будет неэффективным) выделить отдельные моменты.
Взглядом на потоки данных с точки зрения процессов является функциональное программирование (ФП). Оно не оперирует состояниями, для него все данные - это одно большое состояние, над которыми совершаются действия.
ООП и ФП могут дополнять друг друга, если их использовать на разных масштабах архитектуры программного обеспечения: ФП - для моделирования процессов в целом, ООП - для детализации модулей и выделения устойчивых моментов процессов. Неплохое сравнение ООП и ФП можно почитать здесь: https://habr.com/ru/post/474518/
Заключение
Вот мы и закончили. Вот теперь - всё =) Вообще, диалектика - это такая штука, которую можно применять даже в программировании. Надеюсь, я вас в этом убедил. Ведь разработка софта - это, как говорится, работа людей и для людей. Мы все живём в реальном мире, а диалектика его описывает. Было бы круто, если бы кто-то диалектически проанализировал паттерны проектирования.
Подкидываю идею. Бог - это singleton =) А чё такова?) Бога не существует, пока мы о нём не говорим. Как только человек сформулировал понятие бога, он сразу начинает существовать и влиять на ход истории. Он единственный, статический и недоступный для простых смертных объектов. Всё по стандарту)
Также прошу комментировать, ловить ошибки и пробрасывать их наверх (не обрубайте stack trace!). Приходите на кружки. Всем пока!