Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [oop] roznice w obiektach tej samej rodziny
Forum PHP.pl > Forum > PHP > Object-oriented programming
Helios
Witam

Bedzie trudno opisac to co chce osiagnac, jednak mam nadzieje ze jakos zrozumiecie.

Tworze sobie kod, w ktorym potrzebuje miec 3 elementy:

- uzytkownik
- grupa uzytkownikow
- inny

Kazdy z tych elementow jest u mnie reprezentowany przez obiekt typu Type. Obiekty te moge tworzyc i kazdy z nich ma przechowywac i zwracac numer (uzytkownika, grupy lub inny).

W kodzie wyglada to nastepujaco:

  1. <?php
  2. abstract class Type {
  3.  
  4. private $number;
  5.  
  6. public function setNumber($number){
  7. $this->number = $number;
  8. }
  9.  
  10. public function getNumber(){
  11. return $this->number;
  12. }
  13.  
  14. }
  15.  
  16. class User extends Type {
  17.  
  18. public function __construct($number){
  19. $this->setNumber($number);
  20. }
  21.  
  22. }
  23.  
  24. class Group extends Type {
  25.  
  26. public function __construct($number){
  27. $this->setNumber($number);
  28. }
  29.  
  30. }
  31. ?>


Obiekty typu Type wykorzystuje w obiekcie Context:

  1. <?php
  2. class Context {
  3.  
  4. private $type;
  5.  
  6. public function setType(Type $type){
  7. $this->type = $type;
  8. }
  9.  
  10. public function getNumber(){
  11. return $this->type->getNumber();
  12. }
  13.  
  14. }
  15. ?>


Problem polega na tym, ze obiekt Other, typu Type oprocz numeru wymaga innego parametru, ktory musi byc wykorzystany rowniez w kontekscie Context i podany wraz z metoda getNumber:

  1. <?php
  2. class Other extends Type {
  3.  
  4. private $otherField;
  5.  
  6. public function __construct($number, $otherField){
  7. $this->setNumber($number);
  8. $this->setOtherField($otherField);
  9. }
  10.  
  11. public function setOtherField($otherField){
  12. $this->otherField = $otherField;
  13. }
  14.  
  15. public function getOtherField(){
  16. return $this->otherField;
  17. }
  18.  
  19. }
  20. ?>


a w obiekcie Context, po dodaniu obiektu Type i wywolaniu metody getNumber potrzebuje w przypadku obiektu Other pobrac rowniez pole otherField (nazwa tego pola i funkcje beda zmienne w zaleznosci od obiektu typu Type). Moglbym co prawda zrobic na sztywno wykrywanie typu obiektu Type:

  1. <?php
  2. class Context {
  3. //...
  4. public function getNumber(){
  5. if($this->type instanceof Other){
  6. $this->otherField = $this->type->getOtherField();
  7. return $this->type->getNumber();
  8. }else{
  9. return $this->type->getNumber();
  10. }
  11. }
  12. //...
  13. }
  14. ?>


i w przypadku typu Other wymusic pobieranie dodatkowego pola ale w przypadku kilkunastu innych obiektow typu Type lub wielu funkcji dzialajacych w zaleznosci od typu obiektu Type to bedzie malo elastyczne bo bede powielal instrukcje warunkowe itd. Raczej tworzenie kilku rodzin obiektu Context tez nie wchodzi w gre... Jak byscie to rozwiazali?
Myslalem, zeby w metodzie getNumber w klasie Context przekazywac wraz z wywolaniem metody getNumber klasy Type referencje do kontekstu i przekazac na barki obiektow Type zarzadzanie polami w kontekscie. Problem w tym, ze obiekty Type musialby wiedziec o obecnosci kontekstu a tego chce uniknac.
nevt
wg mnie w klasie Contex niepotrzebnie "przykrywasz" metodę getNumber klasy Type - stąd twój problem... lepiej, gdybyś, alalogicznie jak w Type getNumber, zdefiniował metodę getType - wtedy twój problem znika... np.
  1. <?php
  2. //... w klasie Conetxt ...
  3. public function getType()
  4. {
  5. return $this->type;
  6. }
  7. //...
  8. //i wtedy w kodzie odwołujesz się
  9. $user= new Context(new User(1));
  10. $user->getType->getNumber();
  11. //albo
  12. $other= new Context(new Other(2, 'test'));
  13. $other->getType->getNumber();
  14. $other->getType->getOtherField();
  15. //i wszytsko hula
  16. ?>

pozdrawiam.
DeyV
Ewentualnie możesz zrobić jeszcze odrobiną inaczej.

Tworzenie osobnej obsługi dla każdego z typów obiektów danego rodzaju mija się z zasadami tworzenia obiektowego.

Ale przecież Context może działać odrobinę inaczej. Przerzucić ciężar pobierania i wpisywania do siebie dodatkowych informacji na obiekt klasy Type,
np. tak:
  1. <?php
  2. class Type {
  3.  
  4. protected $number;
  5. protected $Context;
  6.  
  7. public function registerContext( Context $Context ){
  8. $this->Context= $Context;
  9. }
  10.  
  11. public function setNumber($number){
  12. $this->number = $number;
  13. }
  14.  
  15. public function getNumber(){
  16. return $this->number;
  17. }
  18.  
  19. }
  20.  
  21. class Other extends Type {
  22.  
  23.  public function getNumber(){
  24. $this->Content-> otherField = $this->getOtherField();
  25. return parent::getNumber();
  26.  }
  27. }
  28.  
  29. class Context {
  30. private $Type;
  31.  
  32. public function setType( Type $type){
  33. $this->Type = $type;
  34. $this->Type->registerContext( $this );
  35. }
  36.  
  37. public function getNumber(){
  38. return $this->type->getNumber();
  39. }
  40.  
  41. }
  42. ?>
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.