Главная страница Случайная страница Разделы сайта АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
💸 Как сделать бизнес проще, а карман толще?
Тот, кто работает в сфере услуг, знает — без ведения записи клиентов никуда. Мало того, что нужно видеть свое раписание, но и напоминать клиентам о визитах тоже.
Проблема в том, что средняя цена по рынку за такой сервис — 800 руб/мес или почти 15 000 руб за год. И это минимальный функционал.
Нашли самый бюджетный и оптимальный вариант: сервис VisitTime.⚡️ Для новых пользователей первый месяц бесплатно. А далее 290 руб/мес, это в 3 раза дешевле аналогов. За эту цену доступен весь функционал: напоминание о визитах, чаевые, предоплаты, общение с клиентами, переносы записей и так далее. ✅ Уйма гибких настроек, которые помогут вам зарабатывать больше и забыть про чувство «что-то мне нужно было сделать». Сомневаетесь? нажмите на текст, запустите чат-бота и убедитесь во всем сами! Наследование и композиция ⇐ ПредыдущаяСтр 6 из 6
Автор: Литягин Денис Наследование является основополагающей концепцией объектно-ориентированного программирования. Но, по неизвестной причине, многие начинающие разработчики стараются уповать лишь на этот принцип и упускают из виду его основного конкурента - композицию. Композиция действительно является основным конкурентом принципа наследования, и многие опытные разработчики рекомендуют использовать именно композицию а не наследование в ряде случаев. К тому же в некоторых языках программирования, хоть это и не критично, композиция выигрывает по производительности в сравнении с наследованием. Давайте рассмотрим что же такой композиция и как ей пользоваться. В стандартной ситуации когда мы хотим создать класс с функционалом другого класса и дополняющего этот функционал своими методами и свойствами мы используем наследование и в классе потомке описываем нужный функционал. Но если взять к примеру язык PHP или же ActionScript мы хоть и редко, но все же столкнемся с проблемой. А именно, отсутствием возможности множественного наследования. Да, многие скажут, что случаи, когда множественное наследование имеет место быть крайне редки, но я могу привести конкретный пример, когда множественное наследование могло бы быть применено. Во время знакомства с фреймворком CakePhp я был озадачен используемой в нем концепции моделей и поведении. Модель в данном фреймворке может иметь неограниченное количество поведений и иметь абсолютно разный функционал. Во времена знакомства с фреймворком мне не хватало опыта чтобы понять суть используемых там конструкций и данный вопрос залег на дно моего сознания до того момента, пока я не побывал на собеседовании в одной московской веб-студии, где мне задали вопрос, поставивший меня в тупик. Звучал он следующим образом: " где бы Вы применили концепцию множественного наследования? ". Именно в тот момент я задумался о том где именно была бы уместной данная концепция объектно-ориентированного программирования. Но ответ пришел уже после. Вспомнив о CakePhp и его поведениях моделей я задумался над понятием композиции. Итак, давайте рассмотрим простой пример. Предположим, что у нас есть модель базы данных. Она имеет стандартный функционал CRUD и, допустим, мы хотим чтобы эта модель работала с древовидными структурами Nested set. Конечно, мы можем описать все необходимые методы внутри модели и все будет работать. Более того, мы сможем унаследовать от нее другие модели которые тоже смогут работать с такими данными. Но, предположим что появится необходимость, чтобы данная модель вела себя не только как Nested set, но и как словарь таксономии, с возможностью связывания терминов между собой и хранила бы в себе количество материалов, использующих конкретные термины. Вот тут встает главный вопрос, как реализовать такую возможность наиболее красивым с точки зрения разработки кода образом. И по скольку множественное наследование отпадает из за того, что не поддерживается языком программирования, на помощь приходит паттерн композиция. Смысл его в следующем. Предположим что у нас есть класс A, который хочет реализовать функциональность классов B и C. Для того чтобы такое было возможно используют следующий подход. Возможно, в сравнении с наследованием данная концепция может не показаться столь красивой и удобной, но ее преимущества нельзя недооценивать. Итак, у нас есть класс A. Он совершенно пуст и не имеет собственных методов и свойств. class A { }Также, у нас есть классы B и C, которые имеют некие методы. Для того, чтобы упростить пример, пусть класс B имеет метод printStrong выводящий текст в браузер, обрамляя его в теги < strong>, а у класс C содержит в себе метод printItalic, выводящие текст обрамленный тегом < i>. class B { public function printStrong($text) { print '< strong> '. $text. '< /strong> '; }} class C { public function printItalic($text) { print '< i> '. $text. '< /i> '; }}Чтобы к нашему классу A можно было обращаться и как к классу B, и как к классу C дополним его некоторым кодом. class A { private $bObject; private $cObject; public function __construct() { $this-> bObject = new B(); $this-> cObject = new C(); } public function printStrong($text) { $this-> bObject-> printStrong($text); } public function printItalic($text) { $this-> cObject-> printItalic($text); }}Как видите, мы не реализовывали заного функционал обоих классов. Все, что мы сделали, это создали в конструкторе класса два объекта классов B и C и присвоили их приватным методам класса A. После чего повторили имена методов обоих классов и делегировали объектам этих классов всю работу. То есть наши методы в классе A по сути являются лишь обертками, позволяющими обращаться к объектам A точно так же как и к объектам классов B и С. Но, у нас осталась проблема. На пример крайне примитивен, в реальном же приложении количество методов может быть очень большим. А ведь нам нужно не забывать делегировать все методы. Здесь на помощь приходят интерфейсы. К счастью в PHP как и в других языках классы могут реализовать несколько интерфейсов одновременно и, соответственно, должен будет реализовать все описанные в них методы. Чтобы наглядно показать как это работает создадим интерфейсы для наших класов B и C. interface BInterface{ public function printStrong($text); } interface CInterface{ public function printItalic($text); }И дополним наши классы. class B implements BInterface { public function printStrong($text) { print '< strong> '. $text. '< /strong> '; }} class C implements CInterface { public function printItalic($text) { print '< i> '. $text. '< /i> '; }}Отныне, имея интерфейсы мы можем быть уверенны в том, что объекты, реализовывающие эти интерфейсы будут иметь все ожидаемые нами методы. Теперь, если бы мы создавали класс A который должен иметь функционал этих двух классов, мы поступили бы по другому и начав писать код, сразу бы объявили с помощью интерфейсов какой именно функционал должен иметь наш универсальный класс. class A implements BInterface, CInterface{ }Теперь по сколку мы указали необходимые интерфейсы мы будем обязаны реализовать необходимые методы из них. А если забудем, PHP сообщит нам о том, что мы не полностью реализовали тот или иной интерфейс. Данный подход позволяет передавать объекты класса A как бы подсовывая их. Следующий код не выдаст ошибки по сколку наш класс A реализовал необходимый интерфейс. $aObject = new A(); function test(CInterface $object) { $object-> printItalic('Test string'); } test($aObject);функция ожидает объект, реализующий интерфейс и ей все равно каким образом данный объект устроен. Главное чтобы были все методы описанные в интерфейсе. Именно по этой причине мы можем подсунуть ему объект класса A, хотя кажется очевидным что здесь место объекту класса C. Таким образом паттерн композиция может быть неплохой заменой множественному наследованию, и в некоторой степени является более простым в понимании написанного в последствии кода. Когда применять наследование, а когда композицию каждый разработчик решает исходя из своих предпочтений. Но по сути выбор прост. Если необходимый класс схож с классом предком, и не будет дополняться функционалом других классов, то наследование - лучшие выбор. Если же требования к нему выше, то композиция будет более уместной.
|