Я помітив, що станом на PHP5 до мови додано інтерфейси. Однак, оскільки PHP настільки слабко набраний, здається, що більшість переваг використання інтерфейсів втрачається. Чому це включено в мову?
Я помітив, що станом на PHP5 до мови додано інтерфейси. Однак, оскільки PHP настільки слабко набраний, здається, що більшість переваг використання інтерфейсів втрачається. Чому це включено в мову?
Відповіді:
Основна перевага інтерфейсів у PHP полягає в тому, що класи можуть реалізувати декілька інтерфейсів. Це дозволяє групувати класи, які поділяють певну функціональність, але не обов'язково поділяють батьківський клас. Деякі приклади можуть включати кешування, вихід чи доступ до властивостей класу певним чином.
У своєму коді ви можете перевірити, чи реалізує клас заданий інтерфейс, а не ім'я класу. Тоді ваш код все ще буде працювати, коли додаються нові класи.
PHP надає деякі заздалегідь задані інтерфейси, які можуть стати в нагоді в різних ситуаціях: http://php.net/manual/en/reserved.interfaces.php .
EDIT - Додавання прикладу
Якщо у вас є інтерфейс з іменем MyInterface і ви працюєте з декількома об'єктами різних класів, які можуть або не мають певної функціональності, інтерфейси дозволяють зробити щось подібне:
// Assume $objects is an array of instances of various classes
foreach($objects as $obj) {
if($obj instanceof MyInterface) {
$obj->a();
$obj->b();
$obj->c();
}
}
PHP набрано слабко, але він може бути сильно набраний щодо таких речей, як параметри методу.
Розглянемо наступний приклад:
interface Car { function go(); }
class Porsche { function go() {} }
function drive(Car $car) {}
$porsche = new Porsche();
drive($porsche);
Вищенаведений код виведе:
Аргумент 1, переданий диску (), повинен реалізувати інтерфейс Car, екземпляр даного Porsche
null
Однак для параметра можна мати значення за замовчуванням.
drive
вимагає Car
проходження, то проходження все null
одно не буде дуже корисним ...
function addView($name, Template $template, SecurityMode $securityMode = null, $methodName = null);
вас може бути, $methodName
але ні $securityMode
.
Інтерфейси дозволяють реалізувати принцип відкритого закритого типу, підтримувати слабко пов'язану базу коду та реалізувати багато найкращих моделей дизайну OOP.
Наприклад, якщо один клас приймає інший клас як аргумент:
class A {
public function __construct(B $class_b) {
// use class b
$class_b->run();
}
}
Тепер ваш клас A і клас B мають щільне з'єднання, а клас A не може використовувати жоден інший клас, крім B. Натяк на тип гарантує, що ви маєте правильний тип аргументу, але тепер цементував зв'язок між A і B.
Скажімо, що ви хочете, щоб клас A міг використовувати всі типи класів, у яких є метод run (), однак. Це в основному (але не зовсім) модель дизайну COMMAND. Щоб вирішити, замість конкретного класу слід набрати підказку, використовуючи інтерфейс. B вони реалізують цей інтерфейс і будуть прийняті як аргумент для класу A. Таким чином клас A може прийняти будь-який клас, який використовує цей інтерфейс як аргумент для свого конструктора.
Цей тип кодування використовується в більшості моделей дизайну OOP, і дозволяє значно пізніше змінити код у наступний час. Це частина основ програмування AGILE.
@pjskeptic має хорошу відповідь , і @Kamil Tomšík має хороший коментар до цієї відповіді.
Чудова річ у динамічно набраних мовах, як PHP, це те, що ви можете спробувати використовувати методи на об’єктах, і він не кричить на вас, якщо методу немає.
Проблема з динамічно набраними мовами, такими як PHP, полягає в тому, що ви можете спробувати використовувати методи на об'єктах, і він буде кричати на вас, коли методу немає.
Інтерфейси додають зручний спосіб виклику методів на невідомому об’єкті, впевнені, що методи існують (не те, що вони обов'язково правильні або працюють). Це не є необхідною частиною мови, але робить кодування більш зручним. Це дозволяє сильно набраним розробникам OOP писати сильно набраний код PHP, який може потім працювати поряд із слабко набраним кодом PHP, написаним іншим розробником PHP.
така функція, як:
foo( IBar $bar )
{
$baz = $bar->baz();
...
}
зручніше ніж:
foo( $bar )
{
if ( method_exists( $bar, 'baz' ) )
{
$baz = $bar->baz();
}
else
{
throw new Exception('OMGWTF NO BAZ IN BAR!');
}
...
}
а IMHO простий, читабельний код - краще код.
Вони абсолютно марні, якщо ти набираєш качок, насправді, коли ти набираєш качок, дуже прикро працювати з бібліотеками / рамками, які використовують будь-які натяки на тип.
Це стосується також усіх видів динамічного метапрограмування (магічні методи).
PHP не є сильно або сильно, але динамічно набирається .
Щодо інтерфейсів, перше, що ви повинні запитати у себе, це: у чому полягають переваги інтерфейсів?
В OOP інтерфейси стосуються не лише типів, а й поведінки.
Оскільки PHP також має функцію підказки типу , ви можете використовувати інтерфейси так само, як у чистому мові oo, наприклад Java.
interface File
{
public function getLines();
}
CSVFile implements File
{
public function getLines()
{}
}
XMLFile implements File
{
public function getLines()
{}
}
JSONFile implements File
{
public function getLines()
{}
}
class FileReader
{
public function read(File $file)
{
foreach($file->getLines() as $line)
{
// do something
}
}
}
З реалізацією інтерфейсу PHP ви також створюєте макети для абстрактних класів за допомогою PHPUnit - і це пекла особливість:
public function testSomething()
{
$mock = $this->getMockForAbstractClass('File');
$mock->expects($this->once())
->method('getLines')
->will($this->returnValue(array()));
// do your assertions
}
Таким чином, ви можете мати в програмі PHP сумісну програму SOLID , використовуючи мовні функції, одним з яких є інтерфейси.
Інтерфейси корисні для введення залежності набагато більше, ніж конкретні. Як приклад босоніжок:
interface Istore {
public function save();
}
class Article_DB implements Istore
{
public function save($data)
{
// do save to format needed.
}
}
class Article
{
private $content;
public function content($content)
{
$this->content = $content;
}
public function save(Istore $store)
{
$store->save($this->content);
}
}
$article = new Article();
$article->content('Some content');
$store = new Article_DB();
$article->save($store);
Тепер скажіть, якщо ваші потреби змінюються, і ви хочете зберегти їх у форматі PDF. Для цього ви можете створити новий клас замість забруднення класу Article.
class Article_PDF implements Istore
{
public function save($data)
{
// do save to format needed.
}
}
$article = new Article();
$article->content('Some content');
$store = new Article_PDF();
$article->save($store);
Клас Article тепер має контракт, що класи, які він використовує для збереження, повинні реалізовувати інтерфейс Istore. Не байдуже, де економить чи як економить.
Ви можете надати "Підроблені" реальні об'єкти, які реалізують інтерфейс. Потім ви можете перевірити частину свого коду, не вимагаючи реальних серверів, файлових систем, сокетів, баз даних тощо.
Багато людей, ймовірно, ненавиджу мене за відповідь таким чином, але рішення ваших проблем із набором тексту можна легко виправити за допомогою PHP. Так, PHP є типово типізованим, тому типи приймаються за замовчуванням, що може спричинити деякі проблеми, особливо в порівнянні з операціями, з якими це стосується більшість людей. Якщо говорити, PHP може бути настільки ж строгим, як і будь-яка сильно набрана мова, якщо ви передаєте те, що ви використовуєте, у потрібний вам тип, а потім використовуєте оператори побітного порівняння. Ось найпростіший приклад, який я можу придумати, про що я говорю:
$ myVar = (int) 0; $ myOtherVar = '0';
порівняння ($ myVar == $ myVar) було б рівним (bool) правдою
але порівняння ($ myVar === $ myVar) було б рівним (bool) помилковим, як і будь-яке "набране" порівняння
Я дуже хочу, щоб розробники перестали сперечатися з приводу цих речей, якщо у вас є проблеми з тим, як працює PHP або перейти на програму Java, і жити, і нехай жити, або використовувати її так, як вона буде робити те, що ви хочете. . Яке користь приносить суті в цьому випадку для вас? Дайте виправдання, щоб викручуватися цілий день? Змусиш виглядати краще, ніж хтось інший? Добре, що ви так високо ставитесь до себе, що ви готові змусити когось іншого виглядати погано, але насправді це ваші уподобання і змушувати свої переконання на когось насправді просто змушує їх кодувати таким чином, що їм не зручно викликати три речі:
1) Вони будуть кодувати ваш шлях, але "безладно" за вашими мірками (подумайте, ви коли-небудь бачили, як програміст java створює свою першу програму PHP чи навпаки? Це буде аналогічно змінити їх методологію чи, можливо, навіть гірше).
2) Ви знайдете щось інше, щоб скуголити
3) Виробництво, ймовірно, займе більше часу. І, можливо, це змусить вас виглядати краще за короткий термін, але команда в цілому буде виглядати гірше за це (пам’ятайте, що ви можете кодувати повільніше, ніж хтось інший, і це не обов'язково погано, якщо команда відповідає розумним результатам, але примушувати свої звички до того, хто зазвичай працює трохи швидше, це може призвести до того, що вся ваша команда сповільниться, таким чином, виглядайте гірше в дуже вимогливому робочому процесі)
Я особисто вважаю за краще писати процедурний PHP-код, хоча я можу і маю написані повні програми, використовуючи OOP на кількох різних мовах. Попри це, я бачив хороший код OOP і поганий код OOP, хороший процесуальний кодекс і поганий процесуальний код з цього приводу ... Це насправді не має нічого спільного з практикою, але з звичками, якими ви користуєтесь і навіть тоді, багато речей - це мої інтерпретовані почуття ... це не означає, що я буду говорити погано про тих розробників або сказати похвалитися "мій шлях найкращий" BS, це мені просто підходить, і компанія, в якій я працюю, досить задоволений своєю роботою і пишаюся цим. Є причини, за якими слід встановити стандарт, але те, що ви включаєте в обраний вами стандарт, ДУЖЕ важливо ... Дякую за те, що дозволили мені вийняти це з грудей. Хорошого дня.
Приклади: потрібно кешувати свої дані. Як? Є багато різних двигунів для кешування, який з них найкращий? Кому байдуже, якщо у вас є абстрактний шар, який має якийсь інтерфейс ICacheDriver з набором методів, таких як ключ, get, put, clear та ін. Просто реалізуйте для нього те, що вам потрібно в поточному проекті, і змініть його, коли вам потрібно інший. Або просте використання ToString. У вас є набір різних об'єктів, що відображаються Ви просто реалізуєте Stringable-інтерфейс (який описує метод toString (у PHP немає насправді таких інтерфейсів, як, наприклад,)) та просто взаємодієте над усім вашим об'єктом з (string) $ obj. Є все, що вам потрібно зробити замість перемикача (true) {case $ obj isntanceof A1: "do 1"; перерву; ...}
Простий. Тож питання "Чому?" Не виникає. Є "як краще це використовувати?". ;-) Удачі.
Моя здогадка.
PHP використовується багатьма програмістами початкового рівня, програмістів початкового рівня навчають Java в коледжі.
Після курсу програмування 101 вони починають нудити Зенда, вони хочуть можливості Java, тому що саме так їх вчили думати, мислити за власними умовами (або розуміти набирання качок) важко, коли вам лише 20 років.
Зенд прагматичний, простіше додати особливість, іншу, ніж робити вигляд там, де все правильно.
Це також купує більше користувачів, а не змушує їх піти, тому це повинно бути добре.
Ще один примірник цього процесу? Люди, що знаходяться на курсах .NET та Java, також хочуть , щоб вони складали рамки фундаментальних класів , і вони не хочуть це доти, доки Zend не виведе Zend Framework . Це купує ще більше користувачів. І далі, і далі ...
(Єдиною мовною особливістю, з якою команда PHP боролася протягом багатьох років, є goto
)
PHP12
напевно, будуть усі синтаксичні особливості світу (я сподіваюся, що він не отримає тривалості шару абстрагування, жорсткий, як це вбило перл) з підморгненням до функціональних і типів парадигм, і досі немає goto
.