Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP/OPP] Klasa abstrakcyjna a interfejs
Forum PHP.pl > Forum > PHP > Object-oriented programming
Staszek27
Witam!
Tworzę sobie stronę WWW. Mam w niej możliwość komentowania konkretnego artykułu jak i wpisanie się do księgi gości. Najlepiej od razu krótka piłka. To jest dobre:
  1. <?php
  2. abstract class wpis {
  3. function pokaz();
  4. function usun();
  5. function dodaj();
  6. }
  7. class wpisDoKsiegi extends wpis {
  8. /* kod */
  9. }
  10. class komentarzDoArtykulu extends wpis {
  11. /* kod */
  12. }
  13. ?>

czy może jednak:
  1. <?php
  2. interface wpis {
  3. function pokaz();
  4. function usun();
  5. function dodaj();
  6. }
  7. class wpisDoKsiegi implements wpis {
  8. /* kod */
  9. }
  10. class komentarzDoArtykulu implemets wpis {
  11. /* kod */
  12. }
  13. ?>

Który jest dobry i dlaczego? A może to w ogóle zły przykład?
Z góry dziękuję za odpowiedź!
Xniver
Ja bym wpis do księgi zrobił tak:
  1. <?php
  2. class GbEntry
  3. {
  4. public $entryData = array();
  5.  
  6. public function __construct($entryData = array())
  7. {
  8. if($entryData)
  9. {
  10. $this->entryData = $entryData;
  11. }
  12. }
  13.  
  14. public function getId()
  15. {
  16. return $this->entryData['id'];
  17. }
  18.  
  19. public function getContent()
  20. {
  21. return $this->entryData['content'];
  22. }
  23.  
  24. public function setId($newId)
  25. {
  26. $this->entryData['id'] = $newId;
  27. }
  28.  
  29. public function setContent($newContent)
  30. {
  31. $this->entryData['content'] = $newContent;
  32. }
  33.  
  34. public function delete()
  35. {
  36. // Usunięcie wpisu(korzystając z Id)
  37. }
  38.  
  39. public function save()
  40. {
  41. if(!isset($this->entryData['id']) || $this->entryData['id'] == 0)
  42. {
  43. // Tutaj tworzymy nowy wpis
  44. }
  45. else
  46. {
  47. // Tutaj aktualizujemy istniejący wpis(używając $this->entryData['id'])
  48. }
  49. }
  50. }
  51.  
  52. // Przykład 1
  53. $query = mysql_query('SELECT * FROM `gb_entries`');
  54.  
  55. while($row = mysql_fetch_assoc($query))
  56. {
  57. $entries[] = new GbEntry($row);
  58. }
  59.  
  60. foreach($entries as $entry)
  61. {
  62. echo $entry->getId() . ': ' . $entry->getContent();
  63. }
  64.  
  65. // Przykład 2
  66. $entry = new GbEntry; // Nowy wpis
  67.  
  68. $entry->setContent('Zawartość'); // Ustawia wartość
  69.  
  70. $entry->save(); // Tworzy nowy wpis w bazie
  71.  
  72. // Przykład 3
  73. $query = mysql_query('SELECT * FROM `gb_entries` WHERE `id` = 1');
  74. $row  = mysql_fetch_assoc($query);
  75. $entry = new GbEntry($row);
  76.  
  77. $entry->setContent('Nowa zawartość'); // Ustawia content
  78. $entry->save(); // Aktualizuje dane
  79.  
  80. $entry->delete(); // Kasuje
  81. ?>


P.S. Jak Ci się takie coś podoba to zajrzyj na stronę Propela
Cysiaczek
@Staszek27 - W tym wypadku lepszy jest interfejs. Abstrakcja od biedy też może być, ale po co marnować możliwość dziedziczenia? inna sprawa, jeśli w tej klasie chcesz zawrzeć jakieś wspólne metody - abstrakcja pasuje wówczas lepiej. Z trzeciej strony, jeśli nawet abstrakcja pasuje lepiej, to czy byłoby uzasadnione umieszczenie w niej takich abstrakcyjnych metod?
Kompromis:
  1. <?php
  2. abstract class MyBaseClass implemets wpis{}
  3.  
  4. class komentarzDoArtykulu extends MyBaseClass{}
  5. ?>


Oczywiście wszystko zależy od potrzeb.
Pozdrawiam.
Staszek27
Dziękuję za odpowiedź. Po prostu nie mogę załapać różnicy pomiędzy interfejsem a klasą abstrakcyjną. Może kiedyś mnie oświeci. :-)
Pozdrawiam!
zzeus
Interfej stosujesz jeśli chcesz mieć pewność że pewne klasy będą zawierać jakieś wspólne metody, ale metody te we wszystkich klasach implementujących ten interfejs są inaczej zaimplementowane. Z kolei klasę abstrakcyjną stosujesz jeśli pewne klasy mają zawierać wspólne metody, ale niektóre z tych metod są tak samo zaimplementowane we wszystkich klasach, czyli implementujesz je w klasie abstrakcyjnej, i w klasach dziedziczących już nie musisz jej implementować.
W sumie nie wiem czy dobrze rozumuje, może niech jeszcze się wypowiedzą mądrzejsci snitch.gif
Cezar708
Cytat(zzeus @ 15.03.2008, 20:24:12 ) *
Interfej stosujesz jeśli chcesz mieć pewność że pewne klasy będą zawierać jakieś wspólne metody, ale metody te we wszystkich klasach implementujących ten interfejs są inaczej zaimplementowane. Z kolei klasę abstrakcyjną stosujesz jeśli pewne klasy mają zawierać wspólne metody, ale niektóre z tych metod są tak samo zaimplementowane we wszystkich klasach, czyli implementujesz je w klasie abstrakcyjnej, i w klasach dziedziczących już nie musisz jej implementować.


dobrze prawisz,
generalizując można powiedzieć tak:

klasa abstrakcyjna: zawiera metody, które już mogą być w niej zaimplementowane, przez co nie trzeba ich implementować w klasie pochodnej (dziedziczącej po klasie abstrakcyjnej), można korzystać już z implementacji w klasie abstrakcyjnej.


interfejs:
NIE ZAWIERA ŻADNYCH IMPLEMENTACJI METOD, jedynie mówi jakie metody MUSI mieć klasa go implementująca.

Cytat(zzeus @ 15.03.2008, 20:24:12 ) *
W sumie nie wiem czy dobrze rozumuje, może niech jeszcze się wypowiedzą mądrzejsci snitch.gif


żeby nie było... za mądrzejszego się nie uważam smile.gif

Pozdrawiam
Staszek27
Dziękuję za odpowiedzi! Ponoć
Cytat
ten naprawdę rozumie, kto rozróżnia
. :-)
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.