Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Interfejsy, czy to jest naprawdę do czegoś potrzebne?
sztosz
post
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
4 Stron V   1 2 3 > »   
Start new topic
Odpowiedzi (1 - 60)
Speedy
post
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.
Go to the top of the page
+Quote Post
wookieb
post
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
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).
Go to the top of the page
+Quote Post
sztosz
post
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
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.
Go to the top of the page
+Quote Post
sztosz
post
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
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? (IMG:style_emoticons/default/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
Go to the top of the page
+Quote Post
LBO
post
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 (IMG:style_emoticons/default/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
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ę
Go to the top of the page
+Quote Post
sztosz
post
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? (IMG:style_emoticons/default/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
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
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
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
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
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
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
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 (IMG:style_emoticons/default/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 (IMG:style_emoticons/default/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 .
Go to the top of the page
+Quote Post
vokiel
post
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
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
vokiel
post
Post #21





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

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


Cytat
Ale nie widzę nigdzie przykładu gdzie interfejs jest nie do zastąpienia w bardzo prosty sposób, a tego szukam.
Raczej takiego przykładu nie znajdziesz, większość (jeśli nie wszystko) da się zrobić na wiele sposobów, czasem dookoła, ale jednak.

Ja osobiście, w przypadku, gdy nie zawrę metody w klasie implementującej po interfejsie wolę jak dostaję komunikat, który nawet pokaże jaki interfejs i jaka metoda została pominięta, niż gdy ma to się ujawnić w momencie próby użycia danej metody.
W przypadku aplikacji, która daje możliwość dodawania modułów. PHPdoc interfejsu jest dość wygodnym rozwiązaniem.

Tak sobie teraz myślę...
Interfejsy dają wielodziedziczenie, jednak tylko pozorne, bo ciała metod i tak trzeba pisać od nowa. Dopiero interfejsy + klasy abstrakcyjne dają możliwość dziedziczenia po wielu klasach z wykorzystaniem już napisanego kodu.
Go to the top of the page
+Quote Post
erix
post
Post #22





Grupa: Moderatorzy
Postów: 15 467
Pomógł: 1451
Dołączył: 25.04.2005
Skąd: Szczebrzeszyn/Rzeszów




Teraz moje trzy grosze. ;p

  1. $obj instanceof MozeSiePoruszac

Z praktycznego punktu widzenia, to chyba jedyny sensowny przykład użytkowania interfejsów w PHP właśnie z tego względu, że nie można definiować ciał metod.

Z tym MozeSiePoruszac, to może nieco abstrakcyjnie, ale można by było to zdefiniować mniej więcej tak: mamy jakąś bibliotekę, która jest zależna tylko od bazy; modele mogą operować na danych z DB albo i z innego źródła, więc modele można by implementować mniej więcej tak:

  1. class zwyczajnaModel implements dbModel {}
  2. class podwawelskaModel implements xmlModel {}


i np. w helperze sprawdzasz:

  1. $this->helperLoader('helperName', $modelObj);
  2. //... helper:
  3. function __construct($modelObj){
  4. if($modelObj instanceof xmlModel){
  5. ...
  6. }
  7. }


Jeśli chodzi o pozostałe przypadki, to w PHP interfejsy są raczej nieco ubogie w praktyczne zastosowanie i wymusza dodatkowe parsowanie kodu... Może się kiedyś doczekamy normalnych interfejsów. (IMG:style_emoticons/default/biggrin.gif)
Go to the top of the page
+Quote Post
dr_bonzo
post
Post #23





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

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


@sztosz

Cytat
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.



Obiektywnie interfejsy maja duzo mniejsza funkcjonalnosc niz klasy abstrakcyjne (nie maja cial metod).

W polaczeniu z konkretnym jezykiem programowania, interfejs i k.abstr. nabywaja nowych wlasciwosci.

Chcesz przyklad gdzie " interfejs jest nie do zastąpienia " ? - Uzyj, "wielodziedziczenia" w php, czy tez javie. Czemu interfejs jest tu lepszym rozwiazaniem? BO NIE MA INNEGO - w php nie masz wielodziedziczenia, rozszerzenia klasy juz uzyles, wiec musisz skorzystac z interfejsu.

Cytat
@vokiel: Ale do tego żeby to zrobić, nie potrzebujesz ani interfejsu, ani klasy abstrakcyjnej, wystarczy po prostu mieć dane metody w klasie sterownika loggera


No pewnie ze wystarcza metody, ale interfejs jest hmm, jak to nazwac, elementem projektowym, dokumentujacym ten zestaw metod jaki implementujesz.
Go to the top of the page
+Quote Post
Cysiaczek
post
Post #24





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




Dziedziczenie to w większości przypadków zło wcielone. Tym bardziej dziedziczenie wielu z klas.
Nie na darmo jeden w twórców Javy (chyba nawet sam James Gosling) powiedział, że jeśli miałby coś zmienić w tym języku, to wywalił by dziedziczenie (IMG:style_emoticons/default/smile.gif)
Interfejsy mają dać typ, metody, pomóc zorganizować projekt. Faktycznie przy codziennej klepaninie nie są przydatne, przynajmniej mi.

Pozdrawiam
Go to the top of the page
+Quote Post
sztosz
post
Post #25





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

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


Cytat(Cysiaczek @ 4.09.2009, 10:22:14 ) *
Dziedziczenie to w większości przypadków zło wcielone. Tym bardziej dziedziczenie wielu z klas.
Nie na darmo jeden w twórców Javy (chyba nawet sam James Gosling) powiedział, że jeśli miałby coś zmienić w tym języku, to wywalił by dziedziczenie (IMG:style_emoticons/default/smile.gif)


Ok, ale dlaczego dziedziczenie to zło?
Go to the top of the page
+Quote Post
Spawnm
post
Post #26





Grupa: Moderatorzy
Postów: 4 069
Pomógł: 497
Dołączył: 11.05.2007
Skąd: Warszawa




Bo w większości przypadków jest zbędne , a początkujący OOPowcy wciskają je gdzie się da (IMG:style_emoticons/default/smile.gif)
Oczywiście czasem jest przydatne ale czasem.
Go to the top of the page
+Quote Post
phpion
post
Post #27





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Pierwsze słyszę opinię, że dziedziczenie to zło. Moglibyście rozwinąć temat?
Go to the top of the page
+Quote Post
LBO
post
Post #28





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

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


Cytat(phpion @ 4.09.2009, 12:05:17 ) *
Pierwsze słyszę opinię, że dziedziczenie to zło. Moglibyście rozwinąć temat?


  1. class Core
  2. {
  3. public function doSomething()
  4. {
  5. // etc
  6. }
  7. }


a dalej magia:

  1. class Router extends Core
  2. {
  3. // etc
  4. }
  5.  
  6. class Controller extends Core
  7. {
  8. // etc
  9. }


Bez żadnego pomyślunku.
Go to the top of the page
+Quote Post
nospor
post
Post #29





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




Cytat
Bo w większości przypadków jest zbędne
latanie heliktoperem z domu do pracy też w większości przypadków jest zbędne. mam na podstawie tego rozumieć ze heliktoptery to zło wcielone?

bezsensowna argumentacja (IMG:style_emoticons/default/tongue.gif)
Go to the top of the page
+Quote Post
phpion
post
Post #30





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Równie dobrze można powiedzieć, że klasy to (IMG:style_emoticons/default/aaevil.gif) ponieważ można do nich wpakować czysto strukturalny kod.
Go to the top of the page
+Quote Post
sztosz
post
Post #31





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

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


Używanie intefejsów jest zbędne, a prawie wszyscy PHPowcy wciskają je gdzie się da. (IMG:style_emoticons/default/tongue.gif)

A co do samego dziedziczenia, to fajnie jest opisane po co to i gdzie się przydaje w Thinking in Java.
Go to the top of the page
+Quote Post
Spawnm
post
Post #32





Grupa: Moderatorzy
Postów: 4 069
Pomógł: 497
Dołączył: 11.05.2007
Skąd: Warszawa




Czy napisałem że zło wcielone? Napisałem że przydatne czasem. Czyli latanie helikopterem aby ratować ludzi w górach a nie wycieczka po masło.
Go to the top of the page
+Quote Post
nospor
post
Post #33





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




Cytat
Czy napisałem że zło wcielone?
No to spojrzmy:
padło pytanie: Ok, ale dlaczego dziedziczenie to zło
na ktore ty odpowiedziales: Bo w większości przypadków jest zbędne , a początkujący OOPowcy wciskają je gdzie się da
Oczywiście czasem jest przydatne ale czasem.

Czyli potwierdziles teze zapytania. a ze czasem przydatne...

Tak czy siak nadal gadasz/gadacie glupoty. Nie wyobrazam sobie OOP bez dziedziczenia. I nie, nie daje tego wszedzie gdzie sie da. Daje wszedzie tam gdzie potrzeba.
Do pracy tez nie latam heliktopterem, ale jakby trzeba było kogoś ratowac to i owszem. Wiec heliktopery sa potrzebne (IMG:style_emoticons/default/tongue.gif)
Go to the top of the page
+Quote Post
phpion
post
Post #34





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Cytat(Spawnm @ 4.09.2009, 12:02:31 ) *
Oczywiście czasem jest przydatne ale czasem.

Stwierdzenie "czasem X ale czasem" jasno daje do zrozumienia, że zazwyczaj tak nie jest więc może nie wypieraj się teraz tego (IMG:style_emoticons/default/smile.gif) Nie napisałeś, że to zło wcielone (napisał to ~Cysiaczek), ale podpisałeś się pod jego słowami.
Go to the top of the page
+Quote Post
Spawnm
post
Post #35





Grupa: Moderatorzy
Postów: 4 069
Pomógł: 497
Dołączył: 11.05.2007
Skąd: Warszawa




OK. W takim razie rozwinę : dziedziczenie to zło w rękach początkującego OOPowca który lata helikopterem po statek aby dopłynąć do sklepu po masło (IMG:style_emoticons/default/tongue.gif)
Go to the top of the page
+Quote Post
nospor
post
Post #36





Grupa: Moderatorzy
Postów: 36 557
Pomógł: 6315
Dołączył: 27.12.2004




No to czego na tak ogolne pytanie odpowiadasz tylko o wybranym gronie uzytkownikow i nie zaznaczysz tego dokladnie.... (IMG:style_emoticons/default/winksmiley.jpg) tylko flame sie tu rodzi niepotrzebnie (IMG:style_emoticons/default/winksmiley.jpg)

Wracając do tematu:
Normalnie nie uzywam interfejsów. Uzywam ich jedynie w klasach/projektach gdy ktoś będzie mogł coś dopisywać swojego i podpinać pod moje. Interfejs zabezpiecza mnie przed tym, ze ktoś coś skopie w metodach i bedzie na mnie.
Przyklad:
napisałem klase cache. Do cache mozna podpiąc rozne sterowniki zapisu cache: pliki, baza danych, pamiec. Każdy może napisac wlasne sterowniki jakie mu przyjdą do głowy. Ja jedynie wymagam by implementowaly one moj interfejs - dzieki temu klasa moze bez problemu uzywac cudzysz sterowników - wiem, ze sie nie wywali na zlej nazwie metody czy na zlych argumentach.
Go to the top of the page
+Quote Post
plurr
post
Post #37





Grupa: Zarejestrowani
Postów: 175
Pomógł: 12
Dołączył: 28.06.2007
Skąd: Bytom

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


Cytat(nospor @ 4.09.2009, 12:57:23 ) *
Wracając do tematu:
Uzywam ich jedynie w klasach/projektach gdy ktoś będzie mogł coś dopisywać swojego i podpinać pod moje. Interfejs zabezpiecza mnie przed tym, ze ktoś coś skopie w metodach i bedzie na mnie.


Podpisuję się pod tym, interfejsy to pewnego rodzaju drogowskazy, powodują że kod się sam dokumentuje. Chociaż czasem może być drażniące skakanie po plikach. Niektórzy zaczynają pisać systemy od zaplanowania fundamentów - interfejsów, a następnie biorą się za pisanie reszty, pozwala to nie odbiegać od ustalonej wcześniej ścieżki.

Mogę też podać pewien przykład implementacji interfejsów:
System oparty na pluginach, nie wiadomo kto będzie pisał nowe pluginy. Ale wiadomo że wstrzykując do klasy bazowej plugin wymagamy, aby posiadał pewne metody. Oczywiście można też użyć ReflectionApi, albo jedno i drugie.

Co do samego dziedziczenia, to wg mnie trzeba je ograniczać - zmiany w klasie po której dziedziczymy, mogą wymusić zmiany w klasach potomnych. Jeśli system posiada zbyt dużo powiązań między klasami to powstaje "obiektowe spagetti".

Ten post edytował plurr 4.09.2009, 13:12:04
Go to the top of the page
+Quote Post
Crozin
post
Post #38





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

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


Cytat
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
Tak więc nie traktuje tylko z perspektywy PHP, gdzie bez interface-ów dałoby się objeść.

W językach typu Java nie wyobrażam sobie pracy bez interface-ów - głównie dlatego, że same w sobie stanowią one osobny typ. Są one również (tu już można mówić o wszystkich językach obsługujących je) niezwykle przydane w przypadku, gdy programiści tworzą kod dla programistów (to co nospor opisał).

Co do "zła w postaci dziedziczenia". Również nie wyobrażam sobie pracy bez niego. A to, że ludzie potrafią źle używać jakiegoś narzędzia to nie argument za tym by uznać narzędzie samo w sobie złym...
Go to the top of the page
+Quote Post
Cysiaczek
post
Post #39





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




Jeśli nieprecyzyjnie się wyraziłem, to sprostuję. Zgadzam się ze @Spawnmem. Chodzi o to, że większość zastosowanych w praktyce relacji dziedziczenia jest "implementacją złego projektu", a więc "złem wcielonym". Dlatego lepiej wszystkim mówić, że dziedziczenie to ZUO, bo może się 3 razy zastanowią nad relacjami w projekcie.
Nie używam dziedziczenia inaczej jak z klasy abstrakcyjnej. Jeśli już to robię ze zwykłej klasy, to znaczy, że pracuję z czyimś kodem, gdzie nie mam wyboru.
Kompozycja jest preferowaną metodą łączenia obiektów, ponieważ jest bardziej elastyczna. Dziedziczenie nie jest elastyczne - jest relacją bardzo sztywną. Prawdopodobnie z powodu nadużywania, Gosling (tak mi się zdaje, że On) powiedział co powiedział.

Pozdrawiam
Go to the top of the page
+Quote Post
batman
post
Post #40





Grupa: Moderatorzy
Postów: 2 921
Pomógł: 269
Dołączył: 11.08.2005
Skąd: 127.0.0.1




Interface jest idealnym przykładem różnicy między teorią, a praktyką.

W teorii interface stanowi punkty wejścia/wyjścia z "black box-a". Blavk box jest tutaj dowolnym tworem, w którym mogą zachodzić różne operacje, o których nie musimy nic wiedzieć. Nas interesuje jedynie w jaki sposób można wykonać operacje na tym pudełku oraz jak pobrać i dostarczyć do niego dane. I tutaj z pomocą przychodzi interface, który nas o tym informuje. W praktyce wszyscy wiemy jak to wygląda.

W teorii programowania obiektowego wszystko jest obiektem (czyli posiada jakiś typ). Bardzo często zdarza się, że dany element musi posiadać dwa lub więcej typów. Można to osiągnąć poprzez wielodziedziczenie (mądre głowy zarzuciły ten pomysł, czyli musiał się nie sprawdzić), stworzenie potężnego drzewa zależności (nie muszę chyba pisać jak głupi jest to pomysł) oraz dzięki interface-om.

Życiowym przykładem, w którym można wytłumaczyć sens istnienia interface-ów i ich zastosowanie jest operator sumowania. Weźmy taki przykład:
x + y
gdzie x = 1, a y = 2.
Wynikiem takiej operacji będzie 3. Ale skąd ma o tym wiedzieć kompilator/parser? Stąd, że do operatora przekazywane są dwie wartości o typach liczba. Jednak, skąd ten typ się wziął? Wziął się z interface-u, po którym dziedziczy(niejawnie) nasza zmienna. Poza typem liczba, nasza zmienna może dziedziczyć po interface np. sumowalna lub zmiennoprzecinkowa. Operator sprawdzając czy przekazana zmienna posiada jakiś typ, może wykonać stosowne operacje. Mechanizm ten można ostrożnie porównać do przeciążania metod.
Go to the top of the page
+Quote Post
sztosz
post
Post #41





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

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


Chyba się mylisz ~batman. Parser/kompilator nic nie musi wiedzieć.
Kod
x = 1
y = 2
z = x + y

Jest tożsame z
Kod
x.=(1)
y.=(2)
z.=(x.+(y))


Przynajmniej w Pythonie i Rubym, wydaje mi się że w większość języków naprawdę obiektowych tak jest. Operatory to są de facto funkcje wbudowane w język. I nie ma żadnego chorego dziedziczenia po interfejsie zmiennoprzecinkowa ( O.o WTF?!?). Po co typ liczby zmiennoprzecinkowej ma dziedziczyć po jakimkolwiek interfejsie skoro taki interfejs, jak już do tego doszliśmy, jest tylko pomocą dla programisty a nie czymś tak ważnym dla samego języka jak np. zmienna, klasa, czy funkcja/metoda.
Go to the top of the page
+Quote Post
batman
post
Post #42





Grupa: Moderatorzy
Postów: 2 921
Pomógł: 269
Dołączył: 11.08.2005
Skąd: 127.0.0.1




~sztosz pytałeś czysto teoretycznie, abstrahując od konkretnej implementacji (przynajmniej tak to zrozumiałem). Jak to jest w konkretnym kompilatorze/parserze, trzeba już samemu pogrzebać.

A co w takiej sytuacji:
x = abc
y = 2
z = x + y

Co teraz ma zrobić kompilator/parser? Jeśli nie znałby typu (odziedziczonego po interface), wówczas niezłe rzeczy by się działy w pudełkach spod biurka (IMG:style_emoticons/default/winksmiley.jpg)
Go to the top of the page
+Quote Post
sztosz
post
Post #43





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

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


A czemu niby typ ma być dziedziczony po interfejsie?

Kompilator, parser sprawdza czy obiekt x posiada metodę =() i czy argumetnem tej metody może być string (w niektórych językach możliwe jest dodawanie stringów do intów i wtedy nie jawnie te inty są rzutowane na stringi, lub stringi na inty (jeśli te stringi to znaki z zakresu [0-9]), jeśli może to dodaje, jeśli nie to wywala wyjątek.

Pisałem że wiem jak to jest w Pythonie i Rubym, bo nie zagłębiałem się w implentacje tego w innych języków.

Ty gdzieś przeczytałeś o dziedziczeniu typów podstawowych po interfejsach czy sam to wymyśliłeś?
Go to the top of the page
+Quote Post
batman
post
Post #44





Grupa: Moderatorzy
Postów: 2 921
Pomógł: 269
Dołączył: 11.08.2005
Skąd: 127.0.0.1




Cytat
A czemu niby typ ma być dziedziczony po interfejsie?
A dlaczego nie? Interface po to między innymi został stworzony, by dany obiekt mógł mieć kilka typów.

Cytat
Kompilator, parser sprawdza czy obiekt x posiada metodę =() i czy argumetnem tej metody może być string (w niektórych językach możliwe jest dodawanie stringów do intów i wtedy nie jawnie te inty są rzutowane na stringi, lub stringi na inty (jeśli te stringi to znaki z zakresu [0-9]), jeśli może to dodaje, jeśli nie to wywala wyjątek.
Refaktorin mimo swoich niezaprzeczalnych zalet, ma jedną wadę - jest wolny. Znacznie szybciej sprawdzisz typ.

Cytat
Ty gdzieś przeczytałeś o dziedziczeniu typów podstawowych po interfejsach czy sam to wymyśliłeś?
Czytałem takie coś na blogu (źródła nie podam, nie zapisałem). Oczywiście rozważania autora były czysto teoretyczne - tak samo w moim przypadku. W końcu o to Ci chodziło?
Go to the top of the page
+Quote Post
LBO
post
Post #45





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

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


batman, jak mniemam chodzi Tobie o to samo na czym opiera się składnia LINQ w .NET. Tak?

edit: przeformułowanie

Ten post edytował LBO 5.09.2009, 17:58:28
Go to the top of the page
+Quote Post
Crozin
post
Post #46





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

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


Cytat
skoro taki interfejs, jak już do tego doszliśmy, jest tylko pomocą dla programisty
Gdzie doszliśmy do takiego wniosku? Sam napisałem, że np. w Javie właściwie bez nich nie da się obejść - a jestem tego pewien, mimo iż nie mogę powiedzieć, że mam w tym języku jakieś doświadczenie.

Go to the top of the page
+Quote Post
batman
post
Post #47





Grupa: Moderatorzy
Postów: 2 921
Pomógł: 269
Dołączył: 11.08.2005
Skąd: 127.0.0.1




Cytat(LBO @ 5.09.2009, 18:55:59 ) *
batman, jak mniemam chodzi Tobie o to samo na czym opiera się składnia LINQ w .NET. Tak?

Nie. Chodzi mi tylko i wyłącznie o teorię. Bez żadnej implementacji.
Go to the top of the page
+Quote Post
LBO
post
Post #48





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

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


Cytat(batman @ 5.09.2009, 18:59:34 ) *
Nie. Chodzi mi tylko i wyłącznie o teorię. Bez żadnej implementacji.


Z teorią to tu daleko nie zajdziesz.

Podstawowe LINQ opiera się całkowicie na interfejsach i tyle - każda implementacja działa zupełnie inaczej, więc nie ma co tworzyć klasy bazowej/abstrakcyjnej). +1 dla interfejsów.

Natomiast to o czym ty piszesz, czyli operatory w językach kompilowanych nie opierają się na interfejsach tylko na metodach, które można dopisać do własnych obiektów lub przeciążać.
Go to the top of the page
+Quote Post
batman
post
Post #49





Grupa: Moderatorzy
Postów: 2 921
Pomógł: 269
Dołączył: 11.08.2005
Skąd: 127.0.0.1




LBO
Cytat
Ja tylko niosę pomoc
(IMG:style_emoticons/default/winksmiley.jpg)

Jeśli chciałbym pisać o .NET, to pisałbym w jego kontekście. Autor tematu prosił o wyjaśnienie po co są interface-y, a nie jak działają w konkretnym języku. Przykład z operatorem wydawał mi się najbliższy sercu programisty, więc go wykorzystałem. Nie chodziło mi o zanurzanie się w teorię przeciążania operatorów, LINQ, czy w konkretną implementację interface-ów. Moje rozważania są czysto teoretyczne i mają tyle wspólnego z rzeczywistością, co UML - z resztą napisałem to w moim pierwszym poście w tym temacie.
Go to the top of the page
+Quote Post
LBO
post
Post #50





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

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


Cytat(batman @ 5.09.2009, 19:10:55 ) *
Przepraszam.


(IMG:style_emoticons/default/smile.gif)

Jakby na to nie patrzeć czysto teoretycznie LINQ opiera się na wbudowanych w język operatorach i interfejsach z nich korzystających, o! Jest doskonałym przykładem na ich (interfejsów) poparcie ;P

Jedyny szkopuł w nieadekwatności do niedorobionej obiektówki PHP (IMG:style_emoticons/default/sad.gif)

edit: doprecyzowanie

Ten post edytował LBO 5.09.2009, 18:33:08
Go to the top of the page
+Quote Post
batman
post
Post #51





Grupa: Moderatorzy
Postów: 2 921
Pomógł: 269
Dołączył: 11.08.2005
Skąd: 127.0.0.1




Niestety nie poznałem LINQ na tyle, by móc prowadzić dyskusję z jego wykorzystaniem na takim poziomie abstrakcji (IMG:style_emoticons/default/winksmiley.jpg) Pozostawiam pole osobie, która wie o czym pisze (IMG:style_emoticons/default/winksmiley.jpg)
Cytat
Jedyny szkopuł w nieadekwatności do niedorobionej obiektówki PHP

Gdyby się dłużej zastanowić, to z językami obiektowymi jest tak jak z przeglądarkami internetowymi. Niby robią to samo, ale każdy z nich inaczej implementuje standardy. I pewnie stąd są problemy w odbiorze niektórych zagadnień związanych z obiektówką.
Go to the top of the page
+Quote Post
LBO
post
Post #52





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

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


Cytat(batman @ 5.09.2009, 19:37:52 ) *
Gdyby się dłużej zastanowić, to z językami obiektowymi jest tak jak z przeglądarkami internetowymi. Niby robią to samo, ale każdy z nich inaczej implementuje standardy. I pewnie stąd są problemy w odbiorze niektórych zagadnień związanych z obiektówką.

Coś w tym jest.

Abstrahując od wyboru gdzie użyć interfejsu, a gdzie klasy bazowej (i nawiązując do wypowiedzi w tym wątku) to programując języku, który posiada wielokrotne dziedziczenie nie bawiłbym się w interfejsy. Działa to też w drugą stronę - nie zrezygnuje z nich w PHP ze względu na korzyści jakie ze sobą niosą.

Druga sprawa, że wielokrotne dziedziczenie ma tyle samo wrogów, co zwolenników. Ja jestem wrogiem. Interfejsy mimo, że niełatwe w obsłudze mają swoje zalety i trudniej nimi napsuć
Go to the top of the page
+Quote Post
sztosz
post
Post #53





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

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


Cytat(batman @ 5.09.2009, 19:10:55 ) *
Autor tematu prosił o wyjaśnienie po co są interface-y, a nie jak działają w konkretnym języku. Przykład z operatorem wydawał mi się najbliższy sercu programisty, więc go wykorzystałem


Ok, ale akurat typ int dziedziczący po interfejsie dodawanie jest dla mnie poronionym pomysłem i to już tak zupełnie. Pisząc kompilator/interpreter ostatnia rzecz której nam potrzeba to nadmiarowy kod który niczego nam nie daje. Co z tego że int będzie implentował interfejs dodawanie, skoro tak czy inaczej bez względu czy implentuje ten interfejs czy nie musi posiadać metodę dodawanie?

Cytat(batman @ 5.09.2009)
Refaktorin mimo swoich niezaprzeczalnych zalet, ma jedną wadę - jest wolny. Znacznie szybciej sprawdzisz typ.


Nie mam pojęcia co to "Refaktorin", zakładam że to czysta literówka i masz na myśli "Refactoring", ale wtedy zupełnie nie wiem co masz na myśli pisząc że jest wolny? I jak to się ma do tematu interfejsów? I co to znaczy że szybsze jest sprawdzanie typu od Refactoring? Serio zdębiałem.

Cytat(batman @ 5.09.2009)
Interface po to między innymi został stworzony, by dany obiekt mógł mieć kilka typów.

Interface nie zmienia i nie dodaje typu obiektu, z tego co ja się orientuje to obiekt może być tylko jednego typu. Patrząc najprościej obekt "X" nie może być typu INT oraz STRING. Interface tylko i wyłącznie wymusza metody. Jeżeli mamy interface "Zapisz przekazane dane" i mamy 2 klasy które implentują ten interfejs jedną XML (zapisuje w XML), drugą DB (zapisuje w bazie danych), to czy obiekt XML będzie typu XML i "Zapisz przekazane dane" a drugi będzie typu DB i "Zapisz przekazane dane"? Wywracasz mój świat do góry nogami swoimi postami :/
Go to the top of the page
+Quote Post
Crozin
post
Post #54





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

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


  1. interface Moveable{}
  2. interface BlahBlah{}
  3. class Animal{}
  4. class Dog extends Animal implements Moveable, BlahBlah{}
Obiekt new Dog() jest typu: Dog, Animal, Moveable, BlahBlah. A.. no i jeszcze Object. (IMG:style_emoticons/default/winksmiley.jpg)
Interface-y mogą stanowić osobny, niezależny typ.

Ten post edytował Crozin 5.09.2009, 22:55:39
Go to the top of the page
+Quote Post
sztosz
post
Post #55





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

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


Czy na pewno to ze coś implentuje jakiś interfejs sprawia że obiekt staje się typu klasy której jest obiektem + interfejsów które implentuje? A jeśli klasa pies dziedziczy po ssak, to czy obiekt klasy pies jest typu pies oraz ssak?


Czy na pewno to ze coś implentuje jakiś interfejs sprawia że obiekt staje się typu klasy której jest obiektem + interfejsów które implentuje i klass po których dziedziczy?
Go to the top of the page
+Quote Post
Crozin
post
Post #56





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

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


Tak, ponieważ Pies dziedzicząc po Ssak otrzymuje jego pełen publiczny interface. Tak więc na obiekcie typu Pies można wykonać dokładnie takie same operacje co na obiekcie Ssak. Różnica jest taka, że pies jako bardziej wyspecjalizowany obiekt może jakąś konkretną metodę realizować inaczej, ale sygnatura tej metody pozostaje niezmienna - tj. interface się nie zmienia. Pies może też realizować metody specyficzne tylko dla Pies, ale mamy 100% że możemy na nim operować jak na Ssak.
Z interface-ami jest dokładnie tak samo.

  1. $pies instanceof Ssak; //true

  1. void nakarmMnie(Ssak zwierz); //Przekazanie obiektu typu Pies nie spowoduje błędu
  2.  
  3. //Podobnie jak błędu nie spowoduje:
  4. Pies pies = new Pies(); //class Pies extends Ssak
  5. Ssak zwierze = (Ssak) pies;
Go to the top of the page
+Quote Post
sztosz
post
Post #57





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

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


OK, zwracam więc honor, miałem zupełnie inne wyobrażenie o typach.
Go to the top of the page
+Quote Post
dr_bonzo
post
Post #58





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

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


(odpowiedz na ost. 2 strony postow)

@sztosz

Cytat
Cytat
A co w takiej sytuacji:
x = abc
y = 2
z = x + y

Co teraz ma zrobić kompilator/parser? Jeśli nie znałby typu (odziedziczonego po interface), wówczas niezłe rzeczy by się działy w pudełkach spod biurka

Kompilator, parser sprawdza czy obiekt x posiada metodę =() i czy argumetnem tej metody może być string


1. Odroznij najpierw moment kompilacji od momentu uruchomienia.
2. W statycznych jezykach (java, c,..) w momencie KOMPILACJI kompilator musi wiedziec czy zmienna "x" ma metode "+". Sprawdzane jest to po typie zmiennej.
Deklarujesz "x" jako 'PlusatorInterface x', ktory to interfejs posiada metode "+" i wszystko jest ok

3. Dla dynamicznych jezykow (Ruby, Python, PHP,...), sprawdzane jest czy OBIEKT! (nie zmienna i jej typ) przypisany do "x" posiada metode "+".
To czy uzylismy tu interfejsu nie ma znaczenia, wazne jest tylko posiadanie metody. Dlatego dla tego typu jezykow intefejsy sa stworzone bardziej w celu
dokumentacji, przedstawienia projektu fragmentu systemu, pokazaniu czemu te N klas ma takie same metody, niz sa potrzebne do uruchomienia kodu.


Skad sie wziely interfejsy - bylo mowione 100 razy - zrezygnowano z wielodziedziczenia, autorzy Javy uzali je za ZLO, i zaproponowali interfejsy (chyba oni byli pierwsi).
No i interfejsy sa konieczne w jezykach javo podobnych, ktora nie jest dynamiczna jak php, ruby, python - w ktorych to interfejsy maja mniejsze znaczeni.


Cytat
Interface nie zmienia i nie dodaje typu obiektu, z tego co ja się orientuje to obiekt może być tylko jednego typu.

sztosz, nie obraz sie ale poucz sie javy czy c#. Chociazby podstaw bo z tego co widze to posiadasz znajomosc jedynie dynamicznych jezykow, i pewne rzeczy ci trudniej pojac.

Cytat
Czy na pewno to ze coś implentuje jakiś interfejs sprawia że obiekt staje się typu klasy której jest obiektem + interfejsów które implentuje i klass po których dziedziczy?

Tak.

Kod
class Bubel extends Something implements Countable {...}

Bubel b = new Bubel();
b.bubluj(); // ZMIENNA b jest typu Bubel, na przypisana instancje Bubel i mozesz na niej uzywac metod zaimplementowanych przez ta klase

Countable c = b;  // tutaj przypisales do ZMIENNEJ typu Countable ten sam obiekt, klasy Bubel. Ale zmienna ma typ Countable, wiec uzyjesz TYLKO tych metod ktore posiada ten interfejs.

System.out.println( c.count() );
Go to the top of the page
+Quote Post
bim2
post
Post #59





Grupa: Zarejestrowani
Postów: 1 873
Pomógł: 152
Dołączył: 9.04.2006
Skąd: Berlin

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


Najlepszy przykład podał właśnie Crozin. W Thinking in java jest to pięknie pokazane na przykładzie zwierzaków.

Intrefejs określa jakie metody musisz użyć, np jak wyobrażałbyś sobie stworzenie for each dla własnej klasy? (IMG:style_emoticons/default/smile.gif) Przecież jak dajesz
  1. MyClass mc = new MyClass();
  2. for(int i:mc)
  3. {
  4.  
  5. }

kompilator musi wiedzieć po czym ma iterować i czy w ogóle może iterować.
implements Iterable i klasa kolejna implements Iterator załatwiają sprawę.
Go to the top of the page
+Quote Post
sztosz
post
Post #60





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

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


Mi się wydawało zawsze że można iterować po czymkolwiek (w rozumienie obiekcie) co posiada metody do iterowania po tym czymś. Np w rubym, jeśli obiekt ma odpowiednio zaimplentowaną metodę each to można używać jej jak iteratora w "typach wbudowane", z times jest podobnie, czy upto. W pythonie masz np. __iter__()

~dr_bonzo słusznie napisał: "sztosz, nie obraz sie ale poucz sie javy czy c#. Chociazby podstaw bo z tego co widze to posiadasz znajomosc jedynie dynamicznych jezykow, i pewne rzeczy ci trudniej pojac." Muszę się pobawić więcej Javą, wtedy zapewne będę inaczej na to wszystko patrzył (IMG:style_emoticons/default/winksmiley.jpg)
Go to the top of the page
+Quote Post
plurr
post
Post #61





Grupa: Zarejestrowani
Postów: 175
Pomógł: 12
Dołączył: 28.06.2007
Skąd: Bytom

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


Nasunęła mi się jeszcze jedna myśl, a propos interfejsów (i nie tylko) - mianowicie: "Wymyślanie koła na nowo".
Co prawda w javie piszę dopiero od paru miesięcy, ale zauważyłem, że każde rozwiązanie jest w pewien sposób udokumentowane np. odpowiednim interfejsem/abstraktem etc. Pisząc tam jakąś klasę, nie skupiam się nad tworzeniem całego drzewa począwszy od Object, ale wykorzystuje już to co tam jest, co mi język dostarcza.

W phpie zaś, niby mamy SPL, ale jest ono wg mnie dosyć ubogie. Można też powiedzieć, że ile programistów, tyle rozwiązań dotyczących jednego problemu.
Go to the top of the page
+Quote Post

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

 



RSS Aktualny czas: 16.09.2025 - 16:18