Это гостевой выпуск Пятиминутки PHP — ведёт Кирилл Сулимовский.
(function(){
var data = {
«addon_key»:»net.veniture.confluence.cloud.macrosuite»,
«uniqueKey»:»net.veniture.confluence.cloud.macrosuite__easy-html6030694237622860366″,
«key»:»easy-html»,
«moduleType»:»dynamicContentMacros», «moduleLocation»:»content», «cp»:»/wiki»,
«general»:»»,
«w»:»100%»,
«h»:»100%»,
«url»:»https://macrosuite.cloud.veniture.net/html?macroId=5d466910-45f4-4208-a89b-bd12e29e7515&pageId=106529405&pageVersion=3&xdm_e=https%3A%2F%2Fmishaikon.atlassian.net&xdm_c=channel-net.veniture.confluence.cloud.macrosuite__easy-html6030694237622860366&cp=%2Fwiki&xdm_deprecated_addon_key_do_not_use=net.veniture.confluence.cloud.macrosuite&lic=none&cv=1.1018.0&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI1YmIzNGM2ODU5ZDg4MTEzYTM3MzkyZWYiLCJxc2giOiI4YmFkYzllYjE5MzhkYjk4OTZiOWI0MmI5OGE5ODY4ZjIzZTZjNmJhNWQzMmEzYzBlOWE5ZmE2YWQ1Y2Y1ZjQ1IiwiaXNzIjoiOWU3NWMxNmEtNmFkYi0zZDVkLTk2ZjgtZDJjY2E2ZDQ5ZDAwIiwiY29udGV4dCI6e30sImV4cCI6MTYyNTQ3NjI4NSwiaWF0IjoxNjI1NDc2MTA1fQ.w5ppKiLTcy-Y91covOd3mMjWsK89Y25OZghjnmc_uQs»,
«contextJwt»: «eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI1YmIzNGM2ODU5ZDg4MTEzYTM3MzkyZWYiLCJxc2giOiJjb250ZXh0LXFzaCIsImlzcyI6IjllNzVjMTZhLTZhZGItM2Q1ZC05NmY4LWQyY2NhNmQ0OWQwMCIsImNvbnRleHQiOnsiY29uZmx1ZW5jZSI6eyJtYWNybyI6eyJvdXRwdXRUeXBlIjoiZW1haWwiLCJoYXNoIjoiNWQ0NjY5MTAtNDVmNC00MjA4LWE4OWItYmQxMmUyOWU3NTE1IiwiaWQiOiI1ZDQ2NjkxMC00NWY0LTQyMDgtYTg5Yi1iZDEyZTI5ZTc1MTUifSwiY29udGVudCI6eyJ0eXBlIjoicGFnZSIsInZlcnNpb24iOiIzIiwiaWQiOiIxMDY1Mjk0MDUifSwic3BhY2UiOnsia2V5IjoiV0lLSSIsImlkIjoiODIyNDc5NCJ9fX0sImV4cCI6MTYyNTQ3NzAwNSwiaWF0IjoxNjI1NDc2MTA1fQ.s5yIoYJkRr6z9-yWcBsz892DPSSKxhZ1Wv6uZHiqOEc», «structuredContext»: «{»confluence»:{»macro»:{»outputType»:»email»,»hash»:»5d466910-45f4-4208-a89b-bd12e29e7515»,»id»:»5d466910-45f4-4208-a89b-bd12e29e7515»},»content»:{»type»:»page»,»version»:»3»,»id»:»106529405»},»space»:{»key»:»WIKI»,»id»:»8224794»}}}»,
«contentClassifier»:»content»,
«productCtx»:»{»page.id»:»106529405»,»macro.hash»:»5d466910-45f4-4208-a89b-bd12e29e7515»,»space.key»:»WIKI»,»user.id»:»5bb34c6859d88113a37392ef»,»page.type»:»page»,»content.version»:»3»,»page.title»:»(L) u041fu0440u0438u043du0446u0438u043f u043fu043eu0434u0441u0442u0430u043du043eu0432u043au0438 u0411u0430u0440u0431u0430u0440u044b u041bu0438u0441u043au043eu0432»,»macro.body»:»»,»: = | RAW | = :»:»theme={\»label\»:\»solarized_dark\»,\»value\»:\»solarized_dark\»}|contentByMode={\»html\»:\»u003ciframe width=\\\»100%\\\» height=\\\»166\\\» scrolling=\\\»no\\\» frameborder=\\\»no\\\» allow=\\\»autoplay\\\» src=\\\»https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/1035321238&color=ff5500&hide_related=true&show_comments=false&show_teaser=false\\\»u003eu003c/iframeu003eu003cdiv style=\\\»font-size: 10px; color: #cccccc;line-break: anywhere;word-break: normal;overflow: hidden;white-space: nowrap;text-overflow: ellipsis; font-family: Interstate,Lucida Grande,Lucida Sans Unicode,Lucida Sans,Garuda,Verdana,Tahoma,sans-serif;font-weight: 100;\\\»u003eu003ca href=\\\»https://soundcloud.com/5minphp\\\» title=\\\»u041fu044fu0442u0438u043cu0438u043du0443u0442u043au0430 PHP\\\» target=\\\»_blank\\\» style=\\\»color: #cccccc; text-decoration: none;\\\»u003eu041fu044fu0442u0438u043cu0438u043du0443u0442u043au0430 PHPu003c/au003e u00b7 u003ca href=\\\»https://soundcloud.com/5minphp/episode88\\\» title=\\\»u041fu0440u0438u043du0446u0438u043f u043fu043eu0434u0441u0442u0430u043du043eu0432u043au0438 u0411u0430u0440u0431u0430u0440u044b u041bu0438u0441u043au043eu0432\\\» target=\\\»_blank\\\» style=\\\»color: #cccccc; text-decoration: none;\\\»u003eu041fu0440u0438u043du0446u0438u043f u043fu043eu0434u0441u0442u0430u043du043eu0432u043au0438 u0411u0430u0440u0431u0430u0440u044b u041bu0438u0441u043au043eu0432u003c/au003eu003c/divu003e\»,\»javascript\»:\»\»,\»css\»:\»\»}»,»space.id»:»8224794»,»contentByMode»:»{\»html\»:\»u003ciframe width=\\\»100%\\\» height=\\\»166\\\» scrolling=\\\»no\\\» frameborder=\\\»no\\\» allow=\\\»autoplay\\\» src=\\\»https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/1035321238&color=ff5500&hide_related=true&show_comments=false&show_teaser=false\\\»u003eu003c/iframeu003eu003cdiv style=\\\»font-size: 10px; color: #cccccc;line-break: anywhere;word-break: normal;overflow: hidden;white-space: nowrap;text-overflow: ellipsis; font-family: Interstate,Lucida Grande,Lucida Sans Unicode,Lucida Sans,Garuda,Verdana,Tahoma,sans-serif;font-weight: 100;\\\»u003eu003ca href=\\\»https://soundcloud.com/5minphp\\\» title=\\\»u041fu044fu0442u0438u043cu0438u043du0443u0442u043au0430 PHP\\\» target=\\\»_blank\\\» style=\\\»color: #cccccc; text-decoration: none;\\\»u003eu041fu044fu0442u0438u043cu0438u043du0443u0442u043au0430 PHPu003c/au003e u00b7 u003ca href=\\\»https://soundcloud.com/5minphp/episode88\\\» title=\\\»u041fu0440u0438u043du0446u0438u043f u043fu043eu0434u0441u0442u0430u043du043eu0432u043au0438 u0411u0430u0440u0431u0430u0440u044b u041bu0438u0441u043au043eu0432\\\» target=\\\»_blank\\\» style=\\\»color: #cccccc; text-decoration: none;\\\»u003eu041fu0440u0438u043du0446u0438u043f u043fu043eu0434u0441u0442u0430u043du043eu0432u043au0438 u0411u0430u0440u0431u0430u0440u044b u041bu0438u0441u043au043eu0432u003c/au003eu003c/divu003e\»,\»javascript\»:\»\»,\»css\»:\»\»}»,»macro.truncated»:»false»,»content.type»:»page»,»output.type»:»email»,»page.version»:»3»,»user.key»:»8a7f808a78f05f9f0178f48910920162»,»content.id»:»106529405»,»macro.id»:»5d466910-45f4-4208-a89b-bd12e29e7515»,»theme»:»{\»label\»:\»solarized_dark\»,\»value\»:\»solarized_dark\»}»}»,
«timeZone»:»Europe/Moscow»,
«origin»:»https://macrosuite.cloud.veniture.net»,
«hostOrigin»:»https://mishaikon.atlassian.net»,
«sandbox»:»allow-downloads allow-forms allow-modals allow-popups allow-scripts allow-same-origin allow-top-navigation-by-user-activation allow-storage-access-by-user-activation», «apiMigrations»: {
«gdpr»: true
}
}
;
if(window.AP && window.AP.subCreate) {
window._AP.appendConnectAddon(data);
} else {
require([‘ac/create’], function(create){
create.appendConnectAddon(data);
});
}
}());
Также порекомендую подписаться на телеграм канал Кирилла: (2)
Принцип подстановки Барбары Лисков
Почему у многих возникают проблемы с этим принципом? Если взять не заумное , а более простое объяснение, то оно звучит так: (1)
«Наследующий класс должен дополнять, а не замещать поведение базового класса».
Звучит логично и понятно, расходимся. но блин, как этого добиться? Почему-то многие просто пропускают мимо ушей следующие строки, которые как раз отлично объясняют что нужно делать.
Рассмотрим выражение «Предусловия не могут быть усилены в подклассе»
Другими словами дочерние классы не должны создавать больше предусловий, чем это определено в базовом классе, для выполнения некоторого бизнесового поведения. Вот несложный пример:
<?php class Customer { protected float $account = 0; public function putMoneyIntoAccount(int|float $sum): void { if ($sum < 1) { throw new Exception('Вы не можете положить на счёт меньше 1$'); } $this->account += $sum; } } class MicroCustomer extends Customer { public function putMoneyIntoAccount(int|float $sum): void { if ($sum < 1) { throw new Exception('Вы не можете положить на счёт меньше 1$'); } // Усиление предусловий if ($sum > 100) { throw new Exception('Вы не можете положить на больше 100$'); } $this->account += $sum; } }
Добавление второго условия как раз является усилением. Так делать не надо!
Контравариантность также можно отнести к данному приниципу. Она касается параметров функции, которые может ожидать подкласс. Подкласс может увеличить свой диапазон параметров, но он должен принять все параметры, которые принимает родительский.
-
Этот пример показывает, как расширение допускается, потому что метод Bar->process() принимает все типы параметров, которые принимает родительский метод.
<?php class Foo { public function process(int|float $value) { // some code } } class Bar extends Foo { public function process(int|float|string $value) { // some code } }
-
В этом примере дочерний класс может принимать более широкий спектр объектов, которые могут быть наследованы от Money, не только Dollars.
<?php class Money {} class Dollars extends Money {} class Customer { protected Money $account; public function putMoneyIntoAccount(Dollars $sum): void { $this->account = $sum; } } class VIPCustomer extends Customer { public function putMoneyIntoAccount(Money $sum): void { $this->account = $sum; } }
Таким образом, мы не добавляем дополнительных проверок, не делаем условия жестче и наш дочерний класс уже ведёт себя более предсказуемо.
В следующих постах мы также рассмотрим постуловия и ковариантность
«Постусловия не могут быть ослаблены в подклассе».
То есть подклассы должны выполнять все постусловия, которые определены в базовом классе. Постусловия проверяют состояние возвращаемого объекта на выходе из функции. Вот такой пример.
<?php class Customer { protected Dollars $account; public function chargeMoney(Dollars $sum): float { $result = $this->account - $sum->getAmount(); if ($result < 0) { // Постусловие throw new Exception(); } return $result; } } class VIPCustomer extends Customer { public function chargeMoney(Dollars $sum): float { $result = $this->account - $sum->getAmount(); if ($sum < 1000) { // Добавлено новое поведение $result -= 5; } // Пропущено постусловие базового класса return $result; } }
Условное выражение проверяющее результат является постусловием в базовом классе, а в наследнике его уже нет. Не делай так!
Сюда-же можно отнести и ковариантность, которая позволяет объявлять в методе дочернего класса типом возвращаемого значения подтип того типа, который возвращает родительский метод.
Короче, в данном примере:
<?php class Image {} class JpgImage extends Image {} class Renderer { public function render(): Image { } } class PhotoRenderer extends Renderer { public function render(): JpgImage { } }
в методе render() дочернего класса, JpgImage объявлен типом возвращаемого значения, который в свою очередь является подтипом Image, который возвращает метод родительского класса Renderer.
Таким образом в дочернем классе мы сузили возвращаемое значение. Не ослабили. А усилили
Все условия базового класса — также должны быть сохранены и в подклассе.
Инварианты — это некоторые условия, которые остаются истинными на протяжении всей жизни объекта. Как правило, инварианты передают внутреннее состояние объекта.
Например типы свойств базового класса не должны изменяться в дочернем.
class Wallet
{
protected float $amount;
// тип данного свойства не должен изменяться в подклассе
}
Здесь также стоит упомянуть исторические ограничения («правило истории»):
Подкласс не должен создавать новых мутаторов свойств базового класса.
Если базовый класс не предусматривал методов для изменения определенных в нем свойств, подтип этого класса так же не должен создавать таких методов. Иными словами, неизменяемые данные базового класса не должны быть изменяемыми в подклассе.
С точки зрения класса Deposit поле не может быть меньше нуля. А вот производный класс VipDeposit, добавляет метод для изменения свойства account, поэтому инвариант класса Deposit нарушается. Такого поведения следует избегать. В таком случае стоит рассмотреть добавление мутатора в базовый класс.
23.04.2021 | Автор Petr Myazin
Источники:
(1) https://5minphp.ru/episode88/
(2) Телеграм канал спикера: https://t.me/beerphp
Нет комментариев