![]() |
![]() |
![]()
Post
#1
|
|
![]() Grupa: Zarejestrowani Postów: 118 Pomógł: 0 Dołączył: 14.02.2004 Skąd: Warszawa Ostrzeżenie: (10%) ![]() ![]() |
Witam. Czy ktoś może mi przedstawić szerzej idee interfejsów, do czego służą, kiedy i po co ich uzywać? Bo nigdzie nie mogę znaleźć konkretnych informacji.
|
|
|
![]() |
![]()
Post
#2
|
|
Grupa: Przyjaciele php.pl Postów: 7 494 Pomógł: 302 Dołączył: 31.03.2004 Ostrzeżenie: (0%) ![]() ![]() |
A naprawdę szukałeś :?:
forum.php.pl -> search -> interfejs Working with Class Types: Abstract Classes and Interfaces |
|
|
![]()
Post
#3
|
|
Grupa: Zarejestrowani Postów: 18 Pomógł: 0 Dołączył: 22.11.2005 Ostrzeżenie: (0%) ![]() ![]() |
Drugi link od mike_mech powinien wszystko wyjaśnić.
Na wszelki wypadek ;) Interfejsy pozwalają pisać lepiej zorganizowany, czytelniejszy kod oraz oddzielać implementację od właśnie interfejsu. Założenia programowania obiektowego mówią o tym, że powinno się pisać kod bardziej ukierunkowany na interfejs, niż samą implementację. Ułatwia to późniejsze ponowne wykorzystywanie kodu i współpracę między projektantami/programistami. Programowanie (w szczególności programowanie komponentowe http://c2.com/cgi/wiki?ComponentOrientedProgramming) to nie tylko pisanie aplikacji dla końcowego użytkownika. Obecnie programiści piszą kod, który jest wykorzystywany/kupowany później przez innych programistów. Aby praca z obcymi komponentami czy bibliotekami była jak najłatwiejsza, czy też w ogóle możliwa, muszą one dostarczać czytelne API http://en.wikipedia.org/wiki/API. Programistę wykorzystującego taki komponent nie interesuję implementacja (czyli w jaki sposób działają poszczególne zadania), a jedynie interfejs (czyli jakie zadania ma możliwość wykonać). Mówiąc prościej… interfejs w odniesieniu do obiektu to po prostu lista metod jakie obiekt posiada wraz z typami niezbędnych parametrów i informacją o zwracanej wartości. php umożliwia wymuszanie jedynie typów obiektowych jako parametrów funkcji. Gorzej jest z wartościami zwracanymi, ale ma się to zmienić http://www.php.net/~derick/meeting-notes.h...d-return-values. Póki co jedyny sposób to dobra dokumentacja kodu http://phpdoc.org/. W taki sposób znając interfejs obiektu wiemy jak go używać. Bo zgodnie z ideą interfejsu wszystkie jego metody muszą być publiczne. Jak sprawa ma się w praktyce? Załóżmy, że mamy napisaną aplikację opartą o Front Controller http://www.phppatterns.com/docs/design/the...troller_and_php, który stanowi punkt wejścia do naszej aplikacji. Możemy w nim rejestrować filtry http://java.sun.com/blueprints/corej2eepat...tingFilter.html, które będą wykonywały jakieś operacje na danych wejściowych i wyjściowych. Idea polega na tym, że wykorzystując nasz kontroler w różnych przypadkach, możemy dowolnie komponować zestawy filtrów, lub też tworzyć nowe w miarę potrzeb. W tym celu tworzymy interfejs filtru, z którym będzie współpracował obiekt kontrolera.
Stwórzmy teraz przykładowy filtr:
Z czasem rozwoju aplikacji może się okazać, że przydałby nam się jeszcze inne filtry. Nie ma problemu wystarczy, że zaimplementujemy na nowo nasz interfejs lub zlecimy to komuś innemu. Tak długo jak będziemy trzymać się interfejsu kontroler będzie potrafił sobie z nim poradzić, a my będzimy mogli go spokojnie używać. Chociażby w taki sposób:
|
|
|
![]()
Post
#4
|
|
Administrator PHPedia.pl Grupa: Developerzy Postów: 1 102 Pomógł: 2 Dołączył: 14.09.2003 Ostrzeżenie: (0%) ![]() ![]() |
Ja filtry inaczej rozwiązałem. Nie mam 2 metod pre i post, tylko jedną: executeFilter. A niej jest $this->executeNext() co uruchamia następny filterek jaki jest w łańcuszku aż do ExecFiltra który to odpala akcje. Oczywiście jeśli będzię kod przed executeNext, zostanie to potraktowe jako pre filter, a po metodzie execNext jako post filter.
-------------------- |
|
|
![]()
Post
#5
|
|
Grupa: Zarejestrowani Postów: 18 Pomógł: 0 Dołączył: 22.11.2005 Ostrzeżenie: (0%) ![]() ![]() |
I o to chodzi. Cała idea wzorców poleg przecież na tym, że podają one sposób rozwiązania jakiegoś złożonego problemu, a implementację zostawiają programiście pozwalając na dużą swobodę. Moja implementacja filtrów z koleji wygląda mniej więcej tak:
![]() |
|
|
![]()
Post
#6
|
|
![]() Grupa: Moderatorzy Postów: 1 566 Pomógł: 37 Dołączył: 14.05.2003 Skąd: Kraków ![]() |
Czyli jesli dobrze zrozumiałem, to narzucenie podanych method w interfejsie ?
Swoją drogą, filtry zrobił bym tak: Klasa Filter, która 'przechowuje' dany filter, potem wrzucamy do ExecuteFilter w którym jest tylko metoda np. process, która uruchamia Filter jako plugin. |
|
|
![]()
Post
#7
|
|
![]() Developer Grupa: Moderatorzy Postów: 2 844 Pomógł: 20 Dołączył: 25.11.2003 Skąd: Olkusz ![]() |
Ja może krótko..
Klasy stosujemy jezeli jest zaleznosc "jest jakims\jakas", w przeciwnym wypadku nie zachodzi potrzeba dziedziczenia i stosuje sie szybsze interfejsy. |
|
|
![]()
Post
#8
|
|
Administrator PHPedia.pl Grupa: Developerzy Postów: 1 102 Pomógł: 2 Dołączył: 14.09.2003 Ostrzeżenie: (0%) ![]() ![]() |
Cytat(Ociu @ 2005-12-02 14:22:58) Czyli jesli dobrze zrozumiałem, to narzucenie podanych method w interfejsie ? Oczywiście, przecież interfejs ma za zadanie wymusić konkretne metody publiczne w implementującej klasie, w szczególnych wypadkach nie ma wcale metod np. interfejs Serializable, który pozwala na serializowanie obiekt, to bardziej z Javy chociaż ostatnio chyba też w SPL widziałem. Cytat Klasy stosujemy jezeli jest zaleznosc "jest jakims\jakas", w przeciwnym wypadku nie zachodzi potrzeba dziedziczenia i stosuje sie szybsze interfejsy. Hmm, trochę nie kumam ;] Ja stosuję dziedziczenie tam gdzie chce użyć metod klas rodziców. Czy ja wiem czy interfejsy są szybsze, po prostu nie mają ciała metod. Zresztą tylko interfejsy przydają się głównie przypisaniu aplikacji i pozwalają wykryć za wczasu, że nie ma konkretnej metody, bo polimorfizm w php praktycznie nie istnieje. -------------------- |
|
|
![]()
Post
#9
|
|
![]() Developer Grupa: Moderatorzy Postów: 2 844 Pomógł: 20 Dołączył: 25.11.2003 Skąd: Olkusz ![]() |
Bela - nigdy do konca nie wnikałem jak to jest w php
![]() ![]() W C# naprzykład interfejsy sa szybsze niz dziedziczenie, pozatym badz co badz zajmuja mniej pamieci. Jezeli potrzebujesz uzywac metod, to znaczy ze ta relacja zachodzi, ale wprowadzanie jej na hama jest poprostu dlamnie absurdem ![]() outputBufforPlugin jest Pluginem ![]() |
|
|
![]()
Post
#10
|
|
![]() Grupa: Moderatorzy Postów: 1 566 Pomógł: 37 Dołączył: 14.05.2003 Skąd: Kraków ![]() |
krzysztof f.: jeśli dobrze zrozumiałem, to twoje filtry działają tak, że każdy filter powinien mieć dwa pliki.
1. Jeden plik, który zawiera 'suchy' kod, który jest jakby mózgiem filtru. 2. Drugi plik, który będzie wykonywał całą robotę. Cały filter leci do FilterChain, który jest zarządzany przez FilterManager, który kieruje filtry do iteratora z ArrayAccess i jesli potrzeba to wyświetla wynik. uf.. ![]() |
|
|
![]()
Post
#11
|
|
![]() Grupa: Przyjaciele php.pl Postów: 5 724 Pomógł: 259 Dołączył: 13.04.2004 Skąd: N/A Ostrzeżenie: (0%) ![]() ![]() |
Cytat outputBufforPlugin jest Pluginem ![]() Zgadza sie, masz bazowa klase plugin z abstrakcyjnymi metodami execute() (czy jakos tam) i je przeladowujesz. Z JAVY (Java 2 Podstawy) cytat ze skrotami (nie chce mi sie tyle przepisywac) [moje dopiski]: "W javie interfejs nie jest klasa ale zbiorem wymagan dotyczacych klas, ktore chca dostosowac sie do interfejsu Zazwyczaj dostawca pewnych uslug stwierdza: Jesli twoja klasa jest dopasowana do danego interfejsu, to wykonam usluge. (...) Metoda sort klasy Arrays obiecuje posortowac obiekty tablicy, ale pod jednym warunkiem: obiekty musza nalezec do klas implementujacych interfejs Comparable [nie musza byc tej samej klasy!!!] [musza zaimplementowac jedyna metode: int compateTo( Object innyObiekt );]" Metoda Arrays.sort() pobiera obiekt "typu" Comparable[] (interfejsy zastapily (w pewnym stopniu) wielokrotne dziedziczenie) -- czyli tablice obiektow implementujacyhc interfejs Comparable i jes sortuje. Interfejs (np. Telewizora -- przysicki: ON/OFF, Vol+, Vol-, P+, P- ) okresla metody jakie musi zaimplementowac obiekt aby inny obiekt/user (user TV) znajacy obsluge tego interfejsu mogl sie nim poslugiwac (umiesz obsluzyc jeden telewizor, obsluzysz tez setke innych bez czytania manuala). Oczywiscie obiekt moze implementowac inne interfejsy (TV+Mikrofalowka, co co? ![]() Inny przydlad: interfejs Zepsuwalne (ale glopie slowo) (jedyna medoda: void zepsuj()), jestes typem czlowieka ktory lubi wszystko psuc (taka abstrakcja, jakby co:)). Obiekty implementujace ten interfejs: TV, Video, Komp, MAC, PC, Sun, Impreze, Atmosfera. Dzieki temu ze implementuja ten interfejs mozesz uzyc na nich metody zepsuj(), nawet jak nie posiadaja wspolnej klasy bazowej. ufff... DA-END -------------------- Nie lubię jednorożców.
|
|
|
![]()
Post
#12
|
|
Grupa: Zarejestrowani Postów: 18 Pomógł: 0 Dołączył: 22.11.2005 Ostrzeżenie: (0%) ![]() ![]() |
hmmm
Rozważania na temat w jakich sytuacjach stosować interfejsy a kiedy tworzyć klasy abstrakcyjne są jak najbardziej na miejscu. Nie ma to jednak nic wspólnego z prędkością czy wydajnością. Cytat W C# naprzykład interfejsy sa szybsze niz dziedziczenie, pozatym badz co badz zajmuja mniej pamieci. hwao czy mógłbyś przedstawić jakieś testy wydajnościowe, które ktoś wykonywał i które potwierdzają Twoją teorię? Błędem jest stawianie interfejsów na równi z dziedziczeniem. Obydwa pojęcia oznaczają coś innego i nie są wymienne. Kiedy potrzebujemy z jakiegoś powodu określić jedynie zestaw metod publicznych dla pisanych w przyszłości klas, nie zajmując się implementacją stosujemy interfejsy. Natomiast gdy na tym etapie pojawia się jakaś wspólna logika dla rodziny klas, którą warto jest zawrzeć w klasie bazowej stosujemy klasy abstrakcyjne. To oczywiście duże uproszczenie, a różnic jest dużo więcej. W php np. nie mamy możliwości dziedziczenia po więcej niż jednej klasie, ale możemy za to implementować więcej niż jeden interfejs, a nawet rozszerzać interfejsy po kilku innych. Ilustruje to przykładowy kod:
Cytat bo polimorfizm w php praktycznie nie istnieje. Jak to?? Już w php4 można było stosować dziedziczenie http://www.php.net/manual/en/keyword.extends.php, które jest przecież głównym narzędziem polimorfizmu. Cytat krzysztof f.: jeśli dobrze zrozumiałem, to twoje filtry działają tak, że każdy filter powinien mieć dwa pliki... Prawie : ) Każdy nowy filtr to dokładnie jedna klasa (i jeden plik) dziedzicząca po abstrakcyjnej klasie InterceptingFilter. Kod klienta operuje jedynie na obiekcie FilterManager, który ukrywa przed nim całą obsługę filtrów. Tworząc instancję menadżera filtrów podajemy w konstruktorze FilterManager::__construct() referencję do docelowego obiektu Target, który wykonuje jakąś operację poprzedzaną i zakańczaną działaniem filtrów. Obiekt Target, podobnie jak filtry, musi implementować interfejs IProcessor. Następnie używając metody FilterManager::addFilter() dodajemy zestaw potrzebnych nam filtrów i w odpowiednim momencie odpalamy przetwarzanie FilterManager::processFilter(). Zgdonie z ideą filtrów, FilterManager::processFilter()wywoła metody InterceptingFilter::preProcess() wszystkich filtrów w kolejności ich dodawania, następnie Target::execute() i metody InterceptingFilter::postProcess() w odwrotnej kolejności. |
|
|
![]()
Post
#13
|
|
![]() Developer Grupa: Moderatorzy Postów: 2 844 Pomógł: 20 Dołączył: 25.11.2003 Skąd: Olkusz ![]() |
Cytat(krzysztof f. @ 2005-12-06 12:39:45) Cytat W C# naprzykład interfejsy sa szybsze niz dziedziczenie, pozatym badz co badz zajmuja mniej pamieci. hwao czy mógłbyś przedstawić jakieś testy wydajnościowe, które ktoś wykonywał i które potwierdzają Twoją teorię? Błędem jest stawianie interfejsów na równi z dziedziczeniem. Obydwa pojęcia oznaczają coś innego i nie są wymienne. Wiem ze oznaczaja co innego, aczkolwiek moga miec "podobne zastosowanie". Co do teori, to jest ona oparta na na ksiezce o c# napisanej przez jednego z tworcow tego jezyka. |
|
|
![]() ![]() |
![]() |
Aktualny czas: 21.08.2025 - 12:21 |