ООП в двух словах

ООП — объектно ориентированное программирование.

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

За свойства отвечают свойства класса (могут иметь тип, а также быть только для класса приватными(private), открытыми для всех(public) или только для того(protected)*, кто их наследует)

Также можно дать только определенным классам менять это свойство через поведение (метод, который получает на вход объект и если он проходит фильтрацию меняет скрытое от остальных объектов свойство) или магические методы get/set

Поведение — за поведение отвечают методы, они могут также быть только для этого объекта приватными(private), могут давать дочернему объекту менять себя (protected)*, либо давать возможность менять себя всем объектам(public).

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

Все это называется инкапсуляцией**

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

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

Мы можем представить объект как совокупность объектов и проверить связи их свойств между собой.

Например, у нас есть велосипед, который имеет состав (свойства и они же объекты)

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

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

Данный велосипед может относится к классу велосипедов, например mtb, hard-tail,bmx,trial, двухподвесы и т. д.

Каждый из этих классов (namespace) может иметь определенные схожие черты с другими классами, может быть целая иерархия, например городские велосипеды — это и bmx и hard-tail,не городские соответственно — это и двухподвесы и trial, и здесь достаточно условные разделения, хотя если взять например царство животных или продукты питания или просто зайти в любой маркетплейс мы увидим насколько там четко распределены объекты.

Почему так происходит?

Потому что класс объекта определяется отношением к его поведению пользователя

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

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

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

Но универсальный(простой) объект имеет в основном одно-два свойства, которые можно определить его классом, который в свою очередь будет верхним классом остальных подклассов.

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

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

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

И здесь мы возвращаемся к связи свойства и поведения, это основная проблема разработки при решении которой в определенных задачах повышается понимание поведения объектов на всех уровнях классов

классы и подклассы пишутся через знак «\» и обозначаются резервированным определением namespace

Например: namespace Table/KitchenTable

Все это называется полиморфизмом

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

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

Все это называется наследованием

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

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

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

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

Все это называется абстракция

Мы определили какими могут быть связи между объектами. Теперь посмотрим каким образом мы могли бы менять эти объекты и разложим наше поведение на подклассы:

Мы можем менять саму структуру объектов, отнесем эти способы к структурным.

Мы можем менять поведение (методы) этих объектов, отнесем эти способы к поведенческим.

Мы можем создавать новые объекты, свойства и поведение объектов, отнесем такие способы к порождающим.

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

SOLID

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

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

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

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

D — поведение и свойства объектов классов не должны зависеть от объектов подклассов, но не наоборот, то есть если у нас есть класс столы, то у него более свободные свойства (двухмерная твердая плоская поверхность, высота), а у подкласса кухонные столы свойства (двухмерная твердая плоская поверхность,на которой можно готовить, высота которая удобна для приготовления а также приема пищи)

DRY — не нужно повторять поведение или свойство объекта, если можно использовать его руководствуясь принципам SOLID

KISS — Если есть возможность упростить поведение или уменьшить свойства объекта, нужно это сделать, объект доложен иметь поведение и свойства соответствующие его классу

YAGNI — Система должна иметь только те объекты с которыми она работает или которые в процессе поведения объектов системы могут ей понадобится

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

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

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

MVP — предлагает разработку объектов начинать с минимальной связной структуры, которая в свою очередь следую принципу YAGNI и BDUF в дальнейшем сможет расширятся в зависимости от наших потребностей и содержит в себе Proof of concept — согласно которому только после подтверждения результата работы минимальной системы отвечающего нашим требованиям можно начинать реализовывать расширение нашей системы

Начать дискуссию