Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Klasy i metody abstrakcyjne i finalne
Forum PHP.pl > Forum > PHP > Object-oriented programming
1010
Witam, poznałem właśnie jak działają klasy i metody abstrakcyjne i finalne, ale zupełnie nie wiem do czego można by je wykorzystać w praktyce. Czy ktoś mógłby mi przedstawić jakiś prosty przykład, wraz z wytłumaczeniem "z czym to się je"?

Z góry dziękuje za pomoc...


PS. Moje początki w obiektówce są dosyć trudne.
Ludvik
Klasa abstrakcyjna to uogólnienie klas, które reprezentują obiekty. Dziedzicząc z niej, możesz skonkretyzować niektóre jej cechy i zachowania. Metoda abstrakcyjna służy do określenia interfejsu, lecz nie posiada ciała metody, więc nie można jej wywołać. Klasa z metodą abstrakcyjną jest również abstrakcyjna. Jakiś głupi przykład najlepszy.

  1. <?php
  2. abstract class Zwierze {
  3. public abstract function pobierzNazwe();
  4. }
  5.  
  6. class Pies extends Zwierze {
  7. public function pobierzNazwe() {
  8. return 'Pies';
  9. }
  10. }
  11.  
  12. ...
  13. ?>


Nie stworzysz obiektu klasy Zwierze, bo zwierzę jest bytem dosyć abstrakcyjnym. Możemy wszystkie obiekty traktować jako zwierzęta, ale tak naprawdę są one instancjami innych klas (np. Pies).

Przykład bardziej z życia - wzorzec Template Method.

Jeżeli podpiszesz coś słowem kluczowym final, to nie zmienisz już tego. Klas finalnych nie można dziedziczyć, a metod nadpisywać. W Javie metody finalne nie są wiązane dynamicznie, bo nie ma takiej potrzeby, dzięki czemu nieco zyskuje się na wydajności. Lepiej jednak nie naduzywać tego mechanizmu.

Najlepiej zaopatrz się w jakąś porządną książkę, jest sporo pozycji, które to dokładniej omówią.
1010
a czy nie lepiej ten przykład po prostu zapisać tak:
  1. <?php
  2.  
  3.  
  4. class Pies {
  5. public function pobierzNazwe() {
  6. return 'Pies';
  7. }
  8. }
  9.  
  10. ...
  11. ?>


po co nam ta abstrakcyjna klasa?
Cysiaczek
Wyobraź sobie metodę pobierzPlec();
Ten podział jest wspólny dla wszystkich zwierząt i sposób rozpoznania płci również (nie wnikajmy w szczegóły :roll2: )
Po co zatem robić dla każdego zwierzęcia osobną metodę? Upychasz jedną w klasie abstrakcyjnej i tyle. Dlaczego akurat w abstrakcyjnej? Ano, człowiek jako zwierze inaczej wykonuje pewne czynności, ale takie, które są wspólne dla wszystkich zwierząt.
Podam przykład takiego zróżnicowania (sorry, że pozostanę w kręgu niższych partii ciała)
  1. <?php
  2. //człowiek
  3. function wydalaj(){
  4. //wywołanie prywatnej metody
  5. $this->idzDoLazienki()
  6. //pozostale metody
  7. }
  8.  
  9. //pies
  10. function wydalaj(){
  11. $this->podniesNoge() // tongue.gif
  12. }
  13. ?>


Widać, że jest różnica, ale na poziomie implementacji, dlatego :

  1. <?php
  2. abstract class Zwierze
  3. {
  4.  
  5. abstract function wydalaj();
  6.  
  7. }
  8.  
  9. class Czlowiek extends Zwierze
  10. {
  11.  //musi implemetnować
  12.  function wydalaj()
  13. {
  14.  $this->idzDoLazienki()
  15.  }
  16.  
  17. //konkretna implementacja
  18. private function idzDoLazienki()
  19. {
  20. return $this->wiadomoCo; // tongue.gif
  21. }
  22.  
  23. }
  24. ?>


Pozdrawiam
UDAT
Przykłady dotyczące klas abstrakcyjnych są (moim zdaniem) nietrafione. Zamiast klasy abstrakcyjnych 'Zwierze' powinien być interfejs, ale to tylko moje zdanie.

Do przeczytania:
> OOP. Interfejsy oraz klasy abstrakcyjne, Zabezpieczenie przed programistą?
> Interfejs a klasa abstrakcyjna, różnice i zastosowanie - problem

Pozdrawiam
Cezar708
o k.. ostry przykład smile.gif... ale fakt, dokłądnie takie jest zastosowanie klas abstrakcyjnych. Jest to po prostu uogólnienie, znalezienie wspólnych części (metod i parametrów) dla wielu klas (klas-dzieci)
Cysiaczek
@UDAT - tu chodzi generalnie o pokazanie ogólnych zasad, a konkretne przykłady można zrobić inaczej, choć akurat gdybyśmy mieli wchodzić w szczegóły, to nie zgadzam się z Tobą - tu lepiej pasuje abstrakcja, a ewentualne interfejsy moża dać dodatkowo.

Pozdrawiam.
UDAT
Cytat(Cysiaczek @ 11.08.2007, 19:19:32 ) *
to nie zgadzam się z Tobą - tu lepiej pasuje abstrakcja, a ewentualne interfejsy moża dać dodatkowo.


Chętnie się dowiem dlaczego. Możesz mi to wytłumaczyć?
Cezar708
ponieważ w interfejsie tylko deklarujesz jakie metody ma zawierać klasa go implementująca, jeśli zrobisz klasę nadrzędną może już mieć ciało. Użyjmy przykładu:

  1. <?php
  2. class figura{
  3. private $pole;
  4. public function pobierzPole(){
  5. return $this->pole;
  6. }
  7. public abstract function obliczPole(){}
  8. }
  9.  
  10. class kwadrat extends figura{
  11. private $dlugosc_boku;
  12. function __construct($bok){
  13. $this->dlugosc_boku = $bok;
  14. }
  15. public function obliczPole(){
  16. $pole = pow($this->dlugosc_boku,2);
  17. }
  18. }
  19.  
  20. class trojkatRownoramienny extends figura{
  21. private $dlugosc_podstawy;
  22. private $wysokosc;
  23. function __construct($podst, $wys){
  24. $this->dlugosc_podstawy = $podst;
  25. $this->wysokosc = $wys;
  26. }
  27. public function obliczPole(){
  28. $pole = $this->dlugosc_podstawy * $this->wysokosc / 2;
  29. }
  30. }
  31.  
  32. $kw = new kwadrat(2);
  33. $kw->obliczPole();
  34. echo $kw->pobierzPole();
  35.  
  36. $tr = new trojkatRownoramienny(4,4);
  37. $tr->obliczPole();
  38. echo $tr->pobierzPole();
  39. ?>


teraz pomysl ze chcesz zrobic tak, aby przy kazdym wyswietleniu pola zostalo wyswietlone "huura pole to: ", normalnie musialbyś zmieniać wszystkie klasy pochodne, a tak robisz to w jednym miejscu:

  1. <?php
  2. class figura{
  3. private $pole;
  4. public function pobierzPole(){
  5. return "Huura, pole to: ".$this->pole;
  6. }
  7. public abstract function obliczPole(){}
  8. }
  9. ?>


jeśli chodzi o interfejsy to jedyne co mają zastosowanie to określenie jakie metody muszą w sobie klasy pochodne mieć, czyli w tym przypadku:
  1. <?php
  2. interface figura{
  3. abstract function pobierzPole();
  4. abstract function obliczPole();
  5. }
  6. ?>


i tak resztę trza by było robić w klasach, które korzystają z interface
Cysiaczek
@UDAT - Ze względów praktycznych to Cezar708 moim zdaniem dobrz to wyjaśnił, jeśli jednak chodzi o sama teorię, to logiczne jest, że wszystkie zwerzęta (uściślijmy - ssaki) mają pewien zbiór funkcji, które są wspólne, więc automatycznie podlegaja one dziedziczeniu. Np. zasnij, wydalaj, rozmnazajSie, ustawPlec() itp. Różnią się implementacją i interfejsem szczegółowym (tym który jest użyty bezpośrednio w implementacji)
Gdyby to była aplikacja symulująca zwierzę, to w klasie bazowej zawarłbyś takie składowe jak:
stan - np. czuwanie/sen
plec -samica/samiec

Używając interfejsu (bez dziedziczenia) powielałbyś te składowe w każdej pochodnej, podobnie jak niektóre metody. Skoro zatem tak, czy owak musiałbyś użyć jakiejś klasy bazowej (aby uniknąc tego powielania), to dlaczego od razu nie uprościć sprawy i nie zrobić klasy abstrakcyjnej?

Pozdrawiam.
danielv13
Cytat(Ludvik @ 11.08.2007, 11:46:48 ) *
  1. <?php
  2. abstract class Zwierze {
  3. public abstract function pobierzNazwe();
  4. }
  5.  
  6. class Pies extends Zwierze {
  7. public function pobierzNazwe() {
  8. return 'Pies';
  9. }
  10. }
  11.  
  12. ...
  13. ?>


Masz książke Core PHP Programowanie Wydanie III ? biggrin.gif snitch.gif
UDAT
Cytat(Cysiaczek @ 11.08.2007, 20:46:01 ) *
@UDAT - Ze względów praktycznych to Cezar708 moim zdaniem dobrz to wyjaśnił, jeśli jednak chodzi o sama teorię, to logiczne jest, że wszystkie zwerzęta (uściślijmy - ssaki) mają pewien zbiór funkcji, które są wspólne, więc automatycznie podlegaja one dziedziczeniu. Np. zasnij, wydalaj, rozmnazajSie, ustawPlec() itp. Różnią się implementacją i interfejsem szczegółowym (tym który jest użyty bezpośrednio w implementacji)
Gdyby to była aplikacja symulująca zwierzę, to w klasie bazowej zawarłbyś takie składowe jak:
stan - np. czuwanie/sen
plec -samica/samiec

Używając interfejsu (bez dziedziczenia) powielałbyś te składowe w każdej pochodnej, podobnie jak niektóre metody. Skoro zatem tak, czy owak musiałbyś użyć jakiejś klasy bazowej (aby uniknąc tego powielania), to dlaczego od razu nie uprościć sprawy i nie zrobić klasy abstrakcyjnej?

Pozdrawiam.


Rozumiem różnicę między interfejsem, a klasą abstrakcyjną. Jednak z twojej wypowiedzi zrozumiałem, że "w tym wypadku" oznacza ten konkretny, zaprezentowany przypadek. Później uściśliłeś, że twoja odpowiedź (jak i poprzednika) dotyczyła nie tego konkretnego przypadku, tylko możliwej implementacji hierarchi zwierząt. I w takim przypadku się zgadzam.

Jednak w przedstawionym przypdaku - klasa abstrakcyjna z samymi metodami abstrakcyjnymi uważam, że powinno się stosować interfejsy.

Pozdrawiam.
Ludvik
Cytat(danielv13 @ 12.08.2007, 10:24:53 ) *
Masz książke Core PHP Programowanie Wydanie III ? biggrin.gif snitch.gif

Nie mam winksmiley.jpg Przykład jest trochę oklepany, więc mogło się zdarzyć, że powtórzyłem treść książki smile.gif


Cytat(UDAT @ 12.08.2007, 11:02:12 ) *
Rozumiem różnicę między interfejsem, a klasą abstrakcyjną. Jednak z twojej wypowiedzi zrozumiałem, że "w tym wypadku" oznacza ten konkretny, zaprezentowany przypadek. Później uściśliłeś, że twoja odpowiedź (jak i poprzednika) dotyczyła nie tego konkretnego przypadku, tylko możliwej implementacji hierarchi zwierząt. I w takim przypadku się zgadzam.

Jednak w przedstawionym przypdaku - klasa abstrakcyjna z samymi metodami abstrakcyjnymi uważam, że powinno się stosować interfejsy.

Pozdrawiam.

Zgadza się. Chciałem zapisać ten przykład w trochę inny sposób, ale nie wiem co mnie przed tym powstrzymało. Interfejsy ogólnie są lepszym narzędziem, głównie dzięki możliwości jednoczesnej implementacji wielu interfejsów w jednej klasie. Sam w projektach staram się używać jak najczęściej interfejsów.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.