Witam.
Nie rozumiem paru rzeczy w programowaniu obiektowym, mianowicie sensu interfejsów i abstrakcji. Przecież taki interfejs w ogóle jest niepotrzebny i tylko zwiększa (nieznacznie) rozmiar naszego pliku, albowiem on tylko wymusza zdefiniowanie jakiejś metody. Ogólnie tą metodę możemy zdefiniować bez żadnego interfejsu - efekt ten sam.
<?php //******************** kod 1 interface intf { public function example(); } class klasa implements intf { public function example() { http://www.php.net/echo 'Example function'; } } //******************** //******************** kod 2 class klasa { public function example() { http://www.php.net/echo 'Example function'; } } //******************** // Efekt? Ten sam, a zatem po co te interfejsy?? ?>
<?php //*************** kod 1 abstract class abstr { abstract public function absfunc (); public function example () { http://www.php.net/echo 'example'; } } class klasa extends abstr { public function absfunc () { http://www.php.net/echo 'abstr'; } } //*************** //*************** kod 2 class notabstr { public function example () { http://www.php.net/echo 'example'; } } class klasa extends notabstr { public function absfunc () { http://www.php.net/echo 'abstr'; } } //*************** // Efekt? Ten sam... ?>
http://forum.php.pl/index.php?showtopic=111328
https://forum.4programmers.net/Java/221811-interfejsy_kl_abstrakcyjne_-_po_co_wlasciwie_je_stosowac
Po pierwsze stosuje się PSR-4 http://www.php-fig.org/psr/psr-4/ i interface, trait oraz wszystkie klasy powinny być definiowane w osobnych plikach.
Po drugie implementacja interface w klasie wymusza własną implementację danej metody czyli w twoim pierwszym przykładzie intf::example(). Strukturyzuje też kod.
Załóżmy gdybyś miał:
UserStorageInterface.php
interface UserStorageInterface { public function fetchById($id); public function fetchAll(); }
class DbUserStorage implements UserStorageInterface { }
class ArrayUserStorage implements UserStorageInterface { }
class ExternalServiceUserStorage implements UserStorageInterface { }
$dbUserStorage = new DbUserStorage; http://www.php.net/var_dump($dbUserStorage instanceof UserStorageInterface); // bool(true)
class UserRepository { /** * @var UserStorageInterface */ private $userStorage; /** * UserRepository constructor. * * @param UserStorageInterface $userStorage */ public function __construct(UserStorageInterface $userStorage) { $this->userStorage = $userStorage; } }
Na początku programowania OO też nie rozumiałem w ogóle co to interface i abstract class.
Aktualnie rozumiem to w ten sposób że:
Interfejs i Klasa Abstrakcyjna jest to narzucony przez programistę sposób nazewnictwa metod, taka instrukcja dla innych programistów, lub dla siebie samego.
Interfejs zawiera jedynie deklarację metod, klasa abstrakcyjna może zawierać dodatkowo działające abstrakcyjne metody.
Pisząc swoje proste aplikacje/frameworki nie stosowałem nigdy interfejsów, natomiast bardzo często pisałem klasy abstrakcyjne, może za często.
Z tymi "działającymi abstrakcyjnymi metodami" to się chyba trochę zagalopowałeś. W skrócie interfejs tym różni się od klasy abstrakcyjnej, że definiuje co robi dana klasa, a nie jak.
Interfejs jest po to abyś mógł podpowiedzieć sobie lub innemu programiście czego oczekujesz od danego obiektu klasy, co powinien on umieć zrobić. Gdy np. przyjmujesz obiekt poprzez dependency injection, jak zostało to pokazane wyżej w UserRepository, to możesz się spodziewać że przekazany Ci obiekt będzie robił to co interfejs UserStorageInterface mu każe. Oznacza to że spokojnie w innym miejscu możesz wywoływać na danym obiekcie metody zaimplementowane z interfejsu UserStorageInterface bez obaw że ich tam nie ma i że dostaniesz fatal error podczas wykonywania kodu. Gdy natomiast jesteś zainteresowany tym by skorzystać z UserRepository to od razu wiesz jakie metody powinieneś zaimplementować w swoich obiektach.
Interfejsy są rozwiązaniem wielodziedziczenia, które znane jest z c++, wiec jak potrzebujesz przykładowo 2 klasy które będą miały takie same metody, ale ich działanie będzie inne to najłatwiej zrobić dla nich interfejs i wtedy masz uporządkowana strukturę, a klasa abstrakcyjna to częściowa cześć wspólna dlatego nie da sie stworzyć obiektu takiej klasy. W php mamy jeszcze cechy
@com to co napisałeś to nie jest wielodziedziczenie Wielodziedziczenie jest wtedy gdy klasa dziedziczy po kilku klasach. Namiastką tego są Traits.
Przykład z moich ostatnich wojów. Mam sobie Commands (kilka różnych). Tworzę sobie rozszerzoną wersję każdego. Siłą rzeczy robię extends dla każdego z odpowiedniego Commands.
Jednak moje commands mają wspólne metody. I tu by się przydało wielodziedziczenie żeby wypchnąć te metody do innego wspólnego Command, ale nie da się. I tu wchodzi Traits.
Traitsy jak najbardziej mają sens, zmniejszają rozmiar pliku + nie musisz kopiować tych samych rzeczy do różnych klas. Po prostu mniej pracy.
Hmm, no cóż, może kiedyś postanowię jednak używać te interfejsy i abstrakcje. Przynajmniej ujrzałem jakieś możliwe zastosowanie, dziękuję.
A tak poza tym czemu trzeba dołączać wszystkie klasy w oddzielnych plikach? Osobiście uważam, że wolę mieć deklaracje klas w innym pliku niż ten, w którym będą mi one potrzebne - mniej scrollowania itp., ale czemu każda klasa w oddzielnym pliku? Ma to w ogóle jakiekolwiek znaczenie?
Robi się tak ze względu na autoloader który automatycznie mapuje nazwę pliku na nazwę klasy. I jest dużo bardziej czytelne.
A juz na pewno nie używa się teraz.class.php. to było za czasow początków PHP 5.
Pyton_000 ja wiem co to wielodziedziczenie, może źle się wyraziłem, w cpp było wielodziedziczenie, którego ludzie strasznie nie lubili w takiej postaci w jakiej było, stad wzrosła popularność interfejsów i klas abstrakcyjnych, które pozwalały w takich językach jak np java stworzyć namiastkę tego co było w cpp ale innym sposobem.
No ale jak masz klasę Foo, która będzie abstrakcyjna i cześć wspólna zaimplementujesz a resztę pozostawisz ew nadpiszesz w pochodnej, to da się nie używać traintów
przykład https://github.com/zendframework/zend-diactoros to dało sie napisac znacznie prościej bez traitów, które bardzo często zaciemniają tylko kod
Hej @IAmBoskiM widze, że jestes w dość podobnej sytuacji co ja Tyle, że ja już zrozumiałem co to są interfejsy/abstrakcje i po co
Generalnie masz bardzo dużo racji: one są niemal niepotrzebne w starszych wersjach PHP. W najnowszej 7.0 już jest lepiej ale nadal niedoskonale. Ich znaczenie zrozumiałem dopiero gdy poczytałem kilka książek o programowaniu gdzie opisane są jezyki naprawdę obiektowe
W dobrym języku obiektowym deklarujac jakas funkcje lub metode mozna wymusic by podany argument byl danego typu: byl daną klasą lub implementowal dany interfejs lub rozszerzal daną klase abstrakcyjną.
Spojrz na ten kod:
class pan_domu { public function nakarm_zwierze_miesozerne($zwierze) { $jedzenie = new Mieso(); $zwierze->je($jedzenie); } public function nakarm_zwierze_roslinozerne($zwierze) { $jedzenie = new Salata(); $zwierze->je($jedzenie); } }
$zwierze = new Kot(); $pan = new pan_domu(); $pan_domu->nakarm_zwierze_miesozerne($zwierze);
interface Zwierzeta_Miesozerne { public function je(); private function gryzie(); private function trawi(); private function trawi_mieso(); }
public function nakarm_zwierze_miesozerne($zwierze) {
public function nakarm_zwierze_miesozerne( Zwierzeta_Miesozerne $zwierze) {
kkarpieszuk wszystko fajnie, ale uargumentuj co masz na myśli mówiąc, że "one są niemal niepotrzebne w starszych wersjach PHP". Sorry ale co takiego 7 zmieniła w stosunku do 5?
Ok możemy zwracać konkretny typ i dodali obsługę skalarów, ale to niczego tutaj nie zmieniło.
@com w trakcie pisania doszedlem do tego samego, ale juz nie wykasowalem
w 5 brakuje mi jeszcze deklaracji zwracanych danych, ale ja juz siedze na 7 wiec problemow nie mam
Do autora tematu
Pytasz o znaczenie rzeczy, na temat których powstalo wiele ksiazek. Nie oczekuj ze ktokolwiek tutaj wyjaśni Ci sens. Zamiast ciągnąc temat, polecam Ci książke PHP Objects, Patterns and Practice edycje 3. Jak ja przeczytasz to zrozumiesz ze na ten moment nie masz bladego pojecia o programowaniu obiektowym. Zrozumiesz ze oop to prawdziwa sztuka, a nie tępe napisanie kilku klas - co kazdy potrafi. Pózniej wrocisz pamiecia do tego postu i sam z siebie bedziesz sie smial.
Jesli ludzie kierowali by sie zasadą ,,po co'' to do niczego bysmy nie doszli. Jesli nadal bedziesz szedl na latwizne to nigdy nie bedziesz dobrym programista - w sumie z korzyscia dla mnie bo im mniej konkurencji tym ja wiecej zarobie ; )
Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)