Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

4 Stron V   1 2 3 > »   
Reply to this topicStart new topic
> Interfejsy, czy to jest naprawdę do czegoś potrzebne?
sztosz
post 1.09.2009, 22:06:52
Post #1





Grupa: Zarejestrowani
Postów: 866
Pomógł: 32
Dołączył: 2.06.2004
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


Mam jedno pytanie: Do czego tak na prawdę mogą się przydać interfejsy w programowaniu? Bo za cholerę nie wiem. Szukam unikalnego zastosowania, którego nie dało by się z powodzeniem zastąpić czymś innym i nie znajduję. Do czego to więc?


--------------------
Go to the top of the page
+Quote Post
Speedy
post 1.09.2009, 22:34:36
Post #2





Grupa: Zarejestrowani
Postów: 651
Pomógł: 28
Dołączył: 4.12.2004

Ostrzeżenie: (0%)
-----


Jeśli chodzi o interfejsy w php, to mogą się one przydać np. do budowania prototypu dla jakiegoś zestawu klas, do wymuszania stworzenia konkretnej metody (lub metod) w różnych klasach, do ujednolicenia lub usystematyzowania wybranego zestawu klas. Implementując interfejs nie zapomnimy o żadnej potrzebnej metodzie. Czasem zdarza się, że jakaś aplikacja ma wiele kontrolerów w postaci klas, które mają bardzo podobną budowę tylko pobierają różne dane i na różny sposób je prezentują. Te kontrolery muszą mieć konkretne metody o konkretnych nazwach, które powielają się każdym z nich, ale zwracają co innego. Za pomocą interfejsu możemy automatycznie zapewnić spójność tych kontrolerów i zapewnić uruchomienie każdego kontrolera tylko w przypadku, gdy posiada wszystkie potrzebne metody.


--------------------
Sygnatura niezgodna z regulaminem.
Go to the top of the page
+Quote Post
wookieb
post 1.09.2009, 22:41:15
Post #3





Grupa: Moderatorzy
Postów: 8 989
Pomógł: 1550
Dołączył: 8.08.2008
Skąd: Słupsk/Gdańsk




Przydają się np do tego jak tworzysz klasy elementów formularza. Chcesz, żeby każda klasa elementu musiała zdefiniować pewne metody, właściwości np getHtml, isValid itd.
Dzięki temu masz pewność, że klasy które implementują ten interfejs, będą posiadały podane metody.

Różnica pomiędzy interfejsem a klasą abstrakcyjną to np taka, że możesz implementować wiele interfejsów a dziedziczyć po jednej klasie.


--------------------
Go to the top of the page
+Quote Post
Speedy
post 1.09.2009, 23:05:19
Post #4





Grupa: Zarejestrowani
Postów: 651
Pomógł: 28
Dołączył: 4.12.2004

Ostrzeżenie: (0%)
-----


Cytat
Różnica pomiędzy interfejsem a klasą abstrakcyjną to np taka, że możesz implementować wiele interfejsów a dziedziczyć po jednej klasie.


Nie tylko. W klasie abstrakcyjnej można zdefiniować całe ciało metody, a w interfejsie tylko jej prototyp (dostępność, nazwa, parametry).


--------------------
Sygnatura niezgodna z regulaminem.
Go to the top of the page
+Quote Post
sztosz
post 1.09.2009, 23:31:05
Post #5





Grupa: Zarejestrowani
Postów: 866
Pomógł: 32
Dołączył: 2.06.2004
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


Ale to w takim razie sprowadza się do tego że do interfejs nie daje mi żadnej nowej funkcjonalności jaką dawał by mi klasa abstrakcyjna (inna sprawa że klasa abstrakcyjna nie daje mi niczego czego nie dawała by mi "zwykła" klasa). Bo co za różnica czy dziedziczę po x klas i implentuję y interfejsów, skoro mogę dziedziczyć po x+y klas. A tym samym nadal nie widzę realnej potrzeby zastosowania interfejsów.


Oczywiście nie chcę zaczynać dyskusji o wyższości kodowania z użyciem interfejsów nad kodowaniem bez ich użycia, bo już za duży ze mnie chłopczyk na bójki o niczym z piaskownicy.
Oraz oczywiście rozumiem że interfejsy, czy klasy abstrakcyjne pozwalają na uniknięcie pewnych błędów, ale z drugiej strony dobrze opisany kod + testy jednostkowe też na to pozwalają, i też o tym nie chcę rozmawiać.

Chce wiedzieć czy interfejs ma w jakieś unikalne zastosowanie którego gdzie nie da się go zastąpić niczym innym. Bo jak na razie dla mnie interfejs to taka klasa abstrakcyjna bez definicji metod, a klasa abstrakcyjna to taka klasa której obiektu nie można utworzyć i... tyle.


--------------------
Go to the top of the page
+Quote Post
dr_bonzo
post 1.09.2009, 23:42:55
Post #6





Grupa: Przyjaciele php.pl
Postów: 5 724
Pomógł: 259
Dołączył: 13.04.2004
Skąd: N/A

Ostrzeżenie: (0%)
-----


Cytat
Bo co za różnica czy dziedziczę po x klas i implentuję y interfejsów, skoro mogę dziedziczyć po x+y klas. A tym samym nadal nie widzę realnej potrzeby zastosowania interfejsów.

Cytat
Chce wiedzieć czy interfejs ma w jakieś unikalne zastosowanie którego gdzie nie da się go zastąpić niczym innym. Bo jak na razie dla mnie interfejs to taka klasa abstrakcyjna bez definicji metod, a klasa abstrakcyjna to taka klasa której obiektu nie można utworzyć i... tyle.


1. Chodzi o to ze mozesz dziedziczyc TYLKO po 1 klasie (pomijam np C++ gdzie mozesz po wielu, ale w nim nie masz interfejsow, ktore niejako zastepuja wielokrotne dziedziczenie).

2. Uzywasz edytora z podpowiadaniem skladni? Albo pokoduj troche w Javie/C# - wymuszanie okreslania typow podpowi ci po co sa interfejsy.

3.
Cytat
Oraz oczywiście rozumiem że interfejsy, czy klasy abstrakcyjne pozwalają na uniknięcie pewnych błędów, ale z drugiej strony dobrze opisany kod + testy jednostkowe też na to pozwalają, i też o tym nie chcę rozmawiać.

Tak, bez interfejsow wszytko nadal bedzie dzialac. Interfejsy w php sa wskazowka projektowa: czemu te 5 klas ma takie same metody? co musze zrobic zeby napisac 6ta klase, bo chce zmienic implementacje np. session handlera. W innych jezykach sa tez obejsciem okreslania typow dla zmiennych - bo masz N klas niepolaczonych ze soba, zadna nie dziedziczy po drugiej, ale maja wspolma metode, np validate(), no i jakos musisz okreslic typ przy definiowaniu zmiennej.
Uzywasz: Validator validator; gdzie Validator to nazwa interfejsu z metoda validate(). Dzieki temu kompilator wie jakich metod mozesz uzywac na obiektach przypisanych do tej zmiennej.


--------------------
Nie lubię jednorożców.
Go to the top of the page
+Quote Post
sztosz
post 2.09.2009, 00:07:35
Post #7





Grupa: Zarejestrowani
Postów: 866
Pomógł: 32
Dołączył: 2.06.2004
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


Cytat(dr_bonzo @ 2.09.2009, 00:42:55 ) *
1. Chodzi o to ze mozesz dziedziczyc TYLKO po 1 klasie (pomijam np C++ gdzie mozesz po wielu, ale w nim nie masz interfejsow, ktore niejako zastepuja wielokrotne dziedziczenie).

2. Uzywasz edytora z podpowiadaniem skladni? Albo pokoduj troche w Javie/C# - wymuszanie okreslania typow podpowi ci po co sa interfejsy.

3.
Tak, bez interfejsow wszytko nadal bedzie dzialac. Interfejsy w php sa wskazowka projektowa: czemu te 5 klas ma takie same metody? co musze zrobic zeby napisac 6ta klase, bo chce zmienic implementacje np. session handlera. W innych jezykach sa tez obejsciem okreslania typow dla zmiennych - bo masz N klas niepolaczonych ze soba, zadna nie dziedziczy po drugiej, ale maja wspolma metode, np validate(), no i jakos musisz okreslic typ przy definiowaniu zmiennej.
Uzywasz: Validator validator; gdzie Validator to nazwa interfejsu z metoda validate(). Dzieki temu kompilator wie jakich metod mozesz uzywac na obiektach przypisanych do tej zmiennej.


Ad 1: OD KIEDY mogę dziedziczyć TYLKO po 1 klasie?
Ad 3: Ja nie pytam o konkretny język programowania tylko o teorię, po to temat w Hydeparku. Ale to jest właśnie przykład o który mi chodziło, dziękuję.


--------------------
Go to the top of the page
+Quote Post
dr_bonzo
post 2.09.2009, 00:25:23
Post #8





Grupa: Przyjaciele php.pl
Postów: 5 724
Pomógł: 259
Dołączył: 13.04.2004
Skąd: N/A

Ostrzeżenie: (0%)
-----


1. A od kiedy mozesz? biggrin.gif Na pewno *mozesz* w C++, w Javie nie mozesz, w PHP nie mozesz (http://www.php.net/manual/en/keyword.extends.php ) , w Rubym nie mozesz (tam masz moduly, cos blizej wielodziedziczeniu niz interfejsom), C# - tez nie (googlilem przed chwila)

3.
Cytat
Ad 3: Ja nie pytam o konkretny język programowania tylko o teorię,

Ciezko mowic o teorii kiedy kazdy jezyk jest inny. Mozemy mowic o interfejsach, kiedy za czasow powstawania C++ ich nie bylo.
Java powstala jako "better c++", pozbyli sie wielodziedziczenia, wprowadzili interfejsy itp.

Ten post edytował dr_bonzo 2.09.2009, 00:28:24


--------------------
Nie lubię jednorożców.
Go to the top of the page
+Quote Post
LBO
post 2.09.2009, 03:29:09
Post #9





Grupa: Zarejestrowani
Postów: 1 415
Pomógł: 117
Dołączył: 7.09.2005
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Przede wszystkim interfejsy umożliwiają poprawną modularyzację aplikacji i ułatwiają modelowanie zależności pomiędzy obiektami. Są bardzo przydane przy projektowaniu modeli (domain models).

Pokaże to na prostym przykładzie wyszukiwarki produktów.
  1. interface IProductSearch
  2. {
  3. /**
  4.   * Add product to search engine index
  5.   *
  6.   * @throws Exception
  7.   */
  8. public index(IProduct $product);
  9.  
  10. /*
  11.   * @return IProduct[] array of products hit by search
  12.   * @throws Exception
  13.   */
  14. public search(array $product);
  15. }

Wszyscy wiemy jak wiele jest rozwiązań dotyczących wyszukiwarek, zatem:
  1. class LuceneProductSearch implements IProductSearch
  2. {
  3. public index(IProduct $product)
  4. {
  5. // tutaj używamy np. Zend_Search_Lucene lub Java Bridge
  6. }
  7.  
  8. public search(array $product)
  9. {
  10. // tutaj używamy np. Zend_Search_Lucene lub Java Bridge
  11. }
  12. }
  13.  
  14. // lub
  15.  
  16. class SphinxProductSearch implements IProductSearch
  17. {
  18. protected $pdo;
  19.  
  20. public function __construct(PDO $pdo)
  21. {
  22. $this->pdo = $pdo;
  23. }
  24.  
  25. public index(IProduct $product)
  26. {
  27. // Prawdopodobnie nic nie robimy i korzystamy z automatycznego indeksowania Sphinxa
  28. }
  29.  
  30. public search(array $product)
  31. {
  32. // wysyłamy odpowiednie zapytanie SQL do bazy
  33. }
  34. }

Użycie mogłoby wyglądać w ten sposób:
  1. // Tworzymy i ustawiamy obiekt produktu jak i wyszukiwarki
  2. $product->save($product_search);
  3. // lub
  4. $product->update($product_search);

W powyższym przykładzie jak krowie na rowie wymodelowaliśmy zależność Produkt-Wyszukiwarka przy zapisywaniu i aktualizacji obiektu. Ta zależność może wyglądać tak:
  1. // Teoretycznie można użyć ORM obiektu pod
  2. // warunkiem, że implementuje interfejs IProduct
  3. class DatabaseProduct implemnts IProduct
  4. {
  5. // etc
  6.  
  7. /**
  8.   * @return boolean true on success, false otherwise
  9.   */
  10. public function save(IProductSearch $product_search)
  11. {
  12. $this->pdo->beginTransaction();
  13. try {
  14.  
  15. // W tym miejscu zapisujemy produkt do bazy danych
  16.  
  17. $this->setId($this->pdo->lastInsertId());
  18. $product_search->index($this); // obiekt zapisany, teraz go zaindeksujmy w wyszukiwarce
  19. $this->pdo->commit();
  20. } catch(Exception $e) {
  21. $this->pdo->rollBack();
  22. return false;
  23. }
  24. return true;
  25. }
  26. }


Jeżeli do projektu jeszcze nie wybrano mechanizmu wyszukiwania, można by również zaimplementować pusty obiekt NoneProductSearch, który by zwyczajnie nic nie indeksował i wracał pustą tablicę przy wyszukiwaniu.

------------------------------------------------
Cały kłopot z programowaniem na interfejsach - jak również niechęć programistów - tkwi w instancjonowaniu obiektów. Trzeba się trochę nagimnastykować.

1. Operator new

  1. $product_search = new LuceneProductSearch;
  2. //lub
  3. $product_search = new SphinxProductSearch($this->getContext()->getDatabase()->getDatabaseConnection());


Zwyczajne tworzenie obiektów już nie wystarcza. Potrzeba czegoś bardziej elastycznego, bo można skończyć (np. przy przesiadce z Lucene na Sphinxa) zmieniając nazwę obiektu wyszukiwarki w każdym miejscu, gdzie się jej używa

2. Wzorce kreacyjne i pochodne
  1. $product_search = $this->getContext()->getProductSearch();


Już lepiej. Konfiguracja obiektu odbywa się w jednym miejscu, ale od ilości pisaniny (np. fabryka do każdego obiektu blink.gif ) można szlak trafić.

  1. // Dla uproszczenia załóżmy, że ta konkretna implementacja kontekstu jest
  2. // również fabryką modeli ProductSearch
  3. class myContext extends sfContext
  4. {
  5. // etc
  6.  
  7. /**
  8.   * @return IProductSearch
  9.   */
  10. public function getProductSearch()
  11. {
  12. return new SphinxProductSearch($this->getDatabaseConnection());
  13. }
  14. }


3. Bardziej kompleksowe rozwiązania.

Przykładem takowych są kontenery IoC. Całość tworzenia obiektów jest przekazywana do nich w formie np. wygodnej xmlowej konfiguracji.
  1. $product_repository = $container>get('ProductRepository');
  2. /* @var $product_repository IProductRepository */
  3.  
  4. $product = $productRepository->getProductById($request->getParameter('id'));
  5. /* @var $product IProduct */
  6.  
  7. $product_search = $container>get('ProductSearch'); // Zwraca odpowiednio skonfigurowane LuceneProductSearch lub SphinxProductSearch
  8. /* @var $product_search IProductSearch */
  9.  
  10. // W tym miejscu ustawiamy nowe wartości obiektu $product
  11.  
  12. $product->update($product_search); // et voila
  13. // lub w zalezności, kto jak podchodzi do repozytoriów
  14. $product_repository->save($product);

Go to the top of the page
+Quote Post
Cysiaczek
post 2.09.2009, 07:07:45
Post #10





Grupa: Moderatorzy
Postów: 4 465
Pomógł: 137
Dołączył: 26.03.2004
Skąd: Gorzów Wlkp.




@sztosz - w OOP jest kilka tematów na temat interfejsów, niemal każdy traktuje o sensie ich istnienia. Są tam wymienione wszystkie zalety i wady stosowania interfejsów, wiec aprawde nie rozumiem, po co kolejny temat o tym samym :/
Przenoszę


--------------------
To think for yourself you must question authority and
learn how to put yourself in a state of vulnerable, open-mindedness;
chaotic, confused, vulnerability, to inform yourself.
Think for yourself. Question authority.
Go to the top of the page
+Quote Post
sztosz
post 2.09.2009, 09:58:10
Post #11





Grupa: Zarejestrowani
Postów: 866
Pomógł: 32
Dołączył: 2.06.2004
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


Cytat(dr_bonzo @ 2.09.2009, 01:25:23 ) *
1. A od kiedy mozesz? biggrin.gif Na pewno *mozesz* w C++, w Javie nie mozesz, w PHP nie mozesz, w Rubym nie mozesz,C# - tez nie


Ale w Pythonie mogę, w Perlu mogę.

Dziękuję wszystkim za komentarze.

Cysiaczek ma rację, niepotrzebnie zakładałem taki temat. Czytam i czytam i wychodzi na to że Interfejsy nie dają żadnej niezastępowalnej funkcjonalności.


--------------------
Go to the top of the page
+Quote Post
Crozin
post 2.09.2009, 13:54:34
Post #12





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Cytat
Czytam i czytam i wychodzi na to że Interfejsy nie dają żadnej niezastępowalnej funkcjonalności.
W PHP podstawowym celem interface-ów jest zagwarantowanie, że to z czym masz do czynienia jest tym czego oczekujesz - przynajmniej w części z której będziesz korzystać.
I takiej funkcjonalności nie dają Ci żadne inne elementy języka.

btw: z wielokrotnym dziedziczeniem nie chodziło o coś takiego:
  1. class A{}
  2. class B extends A{}
  3. class C extends B{}
Tylko o
  1. class A{}
  2. class B{}
  3. class C extends A, B{}
Taka konstrukcja w PHP jest niemożliwa.
Go to the top of the page
+Quote Post
sztosz
post 2.09.2009, 14:41:42
Post #13





Grupa: Zarejestrowani
Postów: 866
Pomógł: 32
Dołączył: 2.06.2004
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


Mnie fascynuje Python, PHP denerwuje. Do zagwarantowania że to z czym mam do czynienia jest tym czego oczekuję nie są mi potrzebne interfejsy a specyfikacja, dokumentacja raczej. Poza tym mogę zawsze dziedziczyć po klasie abstrakcyjnej, inna sprawa że nie ma klas abstrakcyjnych w Pythonie, ale to też jest banalnie poste do zaimplentowania. Teraz nasuwa się pytanie: Kiedy wyrzucany jest błąd związany z tym że klasa nie poprawnie implementuje jakiś interfejs, w momencie tworzenia obiektu klasy, czy.... no kiedy?

Cytat(Crozin @ 2.09.2009, 14:54:34 ) *
btw: z wielokrotnym dziedziczeniem nie chodziło o coś takiego:
  1. class A{}
  2. class B extends A{}
  3. class C extends B{}
Tylko o
  1. class A{}
  2. class B{}
  3. class C extends A, B{}
Taka konstrukcja w PHP jest niemożliwa.


Dla mnie wielokrotne dziedziczenie to coś takiego:
[PYTHON] pobierz, plaintext
  1. class A(object):
  2. def a(self):
  3. print 'a'
  4.  
  5. class B(object):
  6. def b(self):
  7. print 'b'
  8.  
  9. class C(A, B):
  10. pass
  11.  
  12. obiekt = C()
  13. obiekt.a()
  14. obiekt.b()
[PYTHON] pobierz, plaintext

rezultat:
Kod
a
b


I cały czas o tym mówię.

Ten post edytował sztosz 2.09.2009, 14:42:27


--------------------
Go to the top of the page
+Quote Post
Crozin
post 2.09.2009, 15:01:34
Post #14





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Cytat
Mnie fascynuje Python, PHP denerwuje.
Mnie też PHP wieloma elementami denerwuje i staram się od niego odejść na rzecz m.in. Javy - ale jest to nadal potężne narzędzie, które oferuje na prawdę wiele.

Cytat
Do zagwarantowania że to z czym mam do czynienia jest tym czego oczekuję nie są mi potrzebne interfejsy a specyfikacja, dokumentacja raczej.
Dokumentacja dokumentacją, kod kodem.
  1. <?
  2. class A{
  3. public function abc(MyInterface $obj){
  4.  
  5. }
  6. }
Takie wymuszenie jest dużo wygodniejsze niż patrzenie po dokumentacji. Poza tym ewentualny błąd:
Cytat
Metoda A:abc() wymaga by pierwszy argument był MyInterface-m
Jest dużo wygodniejszy niż
Cytat
Nie można wykonać metody def() na obiekcie XXX - linia 123, plik abc
Cytat
Poza tym mogę zawsze dziedziczyć po klasie abstrakcyjnej
No właśnie klasy abstrakcyjnej nie możesz użyć zawsze... ba! Użycie jej jest możliwe jedynie w podstawowych przypadkach typu:
  1. <?
  2.  
  3. abstract class Shape{
  4. abstract public function getSomething();
  5. }
  6.  
  7. class Square extends Shape{
  8.  
  9. }
  10.  
  11. //...
  12. public function doSth(Shape $shape)
Co w przypadku gdy Square dziedziczy już po czymś? Nie możesz w nieskończoność dziedziczyć, bo w końcu byś sens tego stracił: Zwierzę -> Ssak -> Człowiek - to jak najbardziej ok. Zwierzę -> Porusza się -> Oddycha -> Mówi -> Ssak -> Człowiek? Ssaki są rozwinięciem "mowy"? Z interfaceami jest to logiczne: Zwierzę(porusza się, oddycha, mówi) -> Ssak -> Człowiek.
Cytat
inna sprawa że nie ma klas abstrakcyjnych w Pythonie, ale to też jest banalnie poste do zaimplentowania.
A w PHP nie ma klas wewnętrznych... ale co to ma do rzeczy?
Cytat
Kiedy wyrzucany jest błąd związany z tym że klasa nie poprawnie implementuje jakiś interfejs, w momencie tworzenia obiektu klasy, czy.... no kiedy?
W przypadku PHP - sprawdzanie czy dana klasa implementuje wszystkie interface-y wykonywane jest w momencie tworzenia obiektu - ale to w manualu można wyczytać.

Cytat
Dla mnie wielokrotne dziedziczenie to coś takiego:
W PHP coś takiego jest niemożliwe.
Go to the top of the page
+Quote Post
sztosz
post 2.09.2009, 16:00:51
Post #15





Grupa: Zarejestrowani
Postów: 866
Pomógł: 32
Dołączył: 2.06.2004
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


No i to jest właśnie ten problem którego chciałem uniknąć. Założyłem temat na Hydeparku, a nie w PHP żeby mi nie tłumaczono co można w PHP a czego nie, bo to mnie zupełnie nie interesuje. Chciałem dowiedzieć się czegoś o interfejsów od bardziej doświadczonych forumowiczów, a i tak dowiaduję się "Co mi da używanie interfejsów w PHP". Jeśli zaraz nie padnie stwierdzenie w stylu "A czegoś się spodziewał, to przecież forum PHP!'' to będę zaskoczony.

Z tego tematu wynika że w PHP interfejs jest tylko pomocnikiem by programista widział co musi zaimplentować, natomiast i tak musi dla każdej klasy implementującej dany interfejs napisać ciało metody. Dziedzicząc zaś po kilku klasach (co w PHP jest nie możliwe) nie musimy tego robić, ale nic nie stoi na przeszkodzie przesłaniania metod klas po których dziedziczymy (owszem tu są tez niedogodności, ale tylko jeśli nieuważnie kodujemy).

[PYTHON] pobierz, plaintext
  1. class Czlowiek(PoruszaSie, Oddycha, Mowi, Ssak, Zwierze):
  2. pass
[PYTHON] pobierz, plaintext

I nie potrzeba mi interfejsów.


--------------------
Go to the top of the page
+Quote Post
Crozin
post 2.09.2009, 16:26:40
Post #16





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Ahh... zapomniałem, że temat miał być ogólny - mój błąd. Przeglądałem przez "Pokaż najnowsze" i nie zwróciłem nawet uwagi na dział.

Wracając do przykładu z królestwem zwierząt. Co wg Ciebie miała by robić (abstrakcyjna) klasa "porusza się"? Przecież człowiek porusza się w zupełnie inny sposób niż bardzo podobna do niego małpa nie wspominając np. o psie czy delfinie (a wszystkie te zwierzęta dziedziczą po: Zwierzę -> Ssak). Tak więc nie ma tutaj po prostu czego dziedziczyć bo każdy z obiektów wykonuje to zupełnie inaczej. Ale z zewnątrz mamy tak jakby ten sam interface, bo każdy z tych wymienionych obiektów potrafi poruszyć się w prawo, w lewo, do przodu oraz do tyłu.
Jeżeli bardzo chciałbyś użyć tutaj dziedziczenia to musiałaby to być abstrakcyjna klasa definiująca jedynie abstrakcyjne metody, a język prog. musiałby umożliwić wielokrotne dziedziczenie. interface natomiast przynosi nam bardzo wygodny mechanizm identyfikacji "możliwości" obiektu:
  1. //powiedzmy, że jesteśmy wew. jakieś metody "obrony przed zagrożeniem"
  2. if($obj->poziomZycia < 30 && $obj instanceof MozeSiePoruszac){
  3. $obj->uciekajByleGdzie();
  4. }else{
  5. $obj->pozegnajSieZZyciem(); //niestety nasz obiekt jest grzybkiem, który nie może uciec
  6. }
Tak więc nawet w PHP (chociaż ten przykład jest od tego języka dosyć mocno oderwany) interface-y pełnią dużo większą rolę niż tylko "pomocnicza".

Ten post edytował Crozin 2.09.2009, 16:27:54
Go to the top of the page
+Quote Post
sztosz
post 2.09.2009, 16:51:06
Post #17





Grupa: Zarejestrowani
Postów: 866
Pomógł: 32
Dołączył: 2.06.2004
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


O widzisz, i zaczynam poniekąd znajdować zastosowanie dla interfejsu.


--------------------
Go to the top of the page
+Quote Post
dr_bonzo
post 2.09.2009, 20:11:58
Post #18





Grupa: Przyjaciele php.pl
Postów: 5 724
Pomógł: 259
Dołączył: 13.04.2004
Skąd: N/A

Ostrzeżenie: (0%)
-----


Cytat
Z tego tematu wynika że w PHP interfejs jest tylko pomocnikiem by programista widział co musi zaimplentować, natomiast i tak musi dla każdej klasy implementującej dany interfejs napisać ciało metody. Dziedzicząc zaś po kilku klasach (co w PHP jest nie możliwe) nie musimy tego robić, ale nic nie stoi na przeszkodzie przesłaniania metod klas po których dziedziczymy (owszem tu są tez niedogodności, ale tylko jeśli nieuważnie kodujemy).


Tak smile.gif To prawda.
Interfejsy sa obejsciem wielokrotnego dziedziczenia (rozwiazaniem zaproponowanym zamiast W. D.), i ich wada jest to ze nie moga zawierac cial metod - bo tak ich tworcy sobie zalozyli smile.gif
Pewnie z perspektywy czasu nie jest to najlepsze rozwiazanie, i wielodziedziczenie sie przydaje (dla php, hmm, chyba mielem kilka chwil gdzie bym z niego skorzystal, ale nie jestem w stanie wymienic - o musialem zduplikowac kilka metod w dwoch roznych hierarchiach klas, a takto podziedziczylbym z 3ciej klasy i po problemie).

PHP poniekad wzorowalo sie na javie w OOP. Jednak w Javie oprocz interfejsow masz tez klasy wewnetrzne, ktore to pozwalaja w pewien sposob wykonac wielodziedziczenie, konkretniej - dodac do klasy zbioru metod z cialami, jednoczesnie kozystajac z pojedynczego dziedziczenia - http://www.javaworld.com/javaworld/jw-10-2...4-multiple.html .


--------------------
Nie lubię jednorożców.
Go to the top of the page
+Quote Post
vokiel
post 3.09.2009, 07:59:04
Post #19





Grupa: Zarejestrowani
Postów: 2 592
Pomógł: 445
Dołączył: 12.03.2007

Ostrzeżenie: (0%)
-----


Osobiście dla mnie interfejsy są zasadne w kilku przypadkach:
Pluginy - gdy plugin musi mieć określone metody (instalacja, dodanie do menu w panelu, sprawdzenie wersji, wyswietlenie na stronie, etc). Interfejs wymusza zastosowanie tych metod, dzięki czemu wiem, że nie dołączę pluginu bez instalatora.

Drivery - ostatnio pisałem loggera. Przedstawię na przykładzie:
  1. <?php
  2. interface logInterface {
  3. public static function error($err);
  4. public static function warn($err);
  5. public static function info($err);
  6. }
  7.  
  8. class logFile implements logInterface {
  9. public static function error($err){
  10. // zapis błędu do pliku
  11. }
  12. public static function warn($err){
  13. // zapis ostrzeżenia do pliku
  14. }
  15. public static function info($err){
  16. // zapis informacji do pliku
  17. }
  18. }
  19. ?>

Każda następna klasa implementująca logInterface musi posiadać te 3 metody. Dzięki temu mogę utworzyć klasę log która będzie przyjmowała obiekty klas implementujących logInterface.
W przypadku zmian, dodaniu innego sterownika logów, użycie będzie zawsze takie samo:
  1. log::info($err);
Wystarczy na początku skryptu zmienić sterownik:
  1. log::addDriver(new logDb());
  2. log::useDriver('logDb');

I już mogę używać logowania do bazy zamiast do pliku, bez zmian w całym kodzie.

Można to osiągnąć przez użycie klasy abstrakcyjnej. W tym przypadku logowanie do pliku odbywa się zupełnie inaczej niż logowanie do bazy. Zatem klasa abstrakcyjna musiałby mieć tylko zarysy metod, bez ciała - co w rezultacie sprowadza się do interfejsu.

Interfejs dodaje warstwę abstrakcji, którą w przypadku zmian łatwo wymienić nie ingerując w cały kod wykorzystujący dane rozwiązanie.


--------------------
Go to the top of the page
+Quote Post
sztosz
post 3.09.2009, 12:04:08
Post #20





Grupa: Zarejestrowani
Postów: 866
Pomógł: 32
Dołączył: 2.06.2004
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


@vokiel: Ale do tego żeby to zrobić, nie potrzebujesz ani interfejsu, ani klasy abstrakcyjnej, wystarczy po prostu mieć dane metody w klasie sterownika loggera. Jak na razie wszyscy piszą o tym gdzie można użyć interfejsu, ale ja sam potrafię znaleźć miliony zastosowań dla interfejsu, lecz nie w tym rzecz. Jak na razie wiem, że w językach które nie mogą dziedziczyć po wielu klasach interfejs jest "kulawym"* zastępcą dziedziczenia po wielu klasach. Ale nie widzę nigdzie przykładu gdzie interfejs jest nie do zastąpienia w bardzo prosty sposób, a tego szukam.

Przykład ~Crozin'a z "object x is instance of Class Y" tam gdzie jest dziedziczenie po wielu klasach nie potrzebuje atrybutu, tam gdzie nie ma tego można i chyba nawet lepiej zastąpić to jakimś atrybutem klasy bazowej. Bo "możeChodzić" pasuje mi bardziej jako booleanowski atrybut a nie jakiaś klasa czy interfejs. W konstruktorze grzybka ustawiamy "możeChodzić = False" a mrówki "możeChodzić = True". Ale za daleko wybiegam chyba z myślami poza temat.


___________
*Kulawym ponieważ nie pozwala tworzyć w interfejsie ciała metody. Ale tak to zostało zaprojektowane i nie mnie oceniać czy to źle czy dobrze.


--------------------
Go to the top of the page
+Quote Post

4 Stron V   1 2 3 > » 
Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 28.04.2024 - 06:35