2010-03-11 17 views
11

Czy istnieje sposób na przechodzenie przez obiekt w celu pobrania danych obiektu nadrzędnego? Z "obiektem nadrzędnym" nie mam na myśli klasy nadrzędnej, ale dosłownie obiektu. Oto przykład, w :-) javascripty światowej:Obiekt nadrzędny w php

$parent->test = "hello world!"; 

$parent->child = new B(); 

Byłoby wspaniale, jeśli mogę uzyskać dostęp do wszystkich danych z rodzicem w obiekcie dziecko:

class B{ 

//I know this doesn't exists, but it's what I wanted do do 
    function B(){ 
     $this->parent = $this->parent(); 
     echo $this->parent->test; //it would ouput "hello world" 
    } 
} 

Na razie moje rozwiązanie jest przekazać obiekt nadrzędny obiektowi potomnemu (jako odniesienie) lub uczynić jednostkę nadrzędną globalną. Czy masz lepsze rozwiązanie?

Dzięki!

+0

to tylko dwa obiekty z odniesieniami do siebie. możesz nazwać je rodzicem i dzieckiem. – Anurag

+0

Dlaczego potrzebujesz, aby dziecko miało referencję do rodzica? Czy jest coś w rodzicu, że dziecko też potrzebuje dostępu? Jeśli tak, lepiej przekazać dziecku wszystko, czego może potrzebować, a nie próbować uzyskać od rodzica. – rojoca

+0

Mam w rodzicu "obiekt prywatności", to niektóre zmienne potrzebuję w dziecku, a przekazanie ich wszystkich byłoby nudne ... – AntonioCorrenti

Odpowiedz

21

Nie ma sposobu, aby wywołać

$parent->test = "hello world!"; 
$parent->child = new B(); 

i automatycznie mają odniesienie do $ rodzica w B.


Generalnie istnieją cztery sposoby, aby zbudować swoje zajęcia:

1. Agreguj obiekt nadrzędny poprzez Injection, np.

class B 
{ 
    private $parent; 

    public function __construct($parent) 
    { 
     $this->parent = $parent; 
    } 

    public function setParent($parent) 
    { 
     $this->parent = $parent; 
    } 

    public function accessParent() 
    { 
     $this->parent->someMethodInParent(); 
    } 
} 

Zastosowanie wtrysku konstruktor, gdy obiekt ma mieć rodzica, gdy jest tworzony. Jest to relacja ma- i tworzy bardzo luźne połączenie. W B nie ma żadnych ściśle zakodowanych zależności, więc można łatwo zamienić instancję nadrzędną, na przykład z próbą, gdy UnitTest. Używanie Dependency Injection spowoduje, że Twój kod będzie łatwiejszy w utrzymaniu.

W swojej USECASE, chcesz przekazać $parent do B podczas tworzenia B:

$parent->child = new B($parent); 

2.Zastosowanie Skład

class B 
{ 
    private $parent; 

    public function __construct() 
    { 
     $this->parent = new Parent; 
    } 

    public function accessParent() 
    { 
     $this->parent->someMethodInParent(); 
    } 
} 

Jest to również ma-relację, ale pary klasy nadrzędnej do B. To również nie istniejąca instancja nadrzędna, ale nowa instancja. Ze sformułowania uważam, że to trochę dziwne, aby mieć rodzica stworzonego przez dziecko. Użyj tego, gdy zależność jest klasą, która nie jest uważana za istniejącą poza klasą root, ale jest częścią całej rzeczy, którą reprezentuje.

Dla Twojego UseCase, nie ma sposobu, aby zrobić $parent->child = new B(); i wiedzieć, co rodzic jest przy użyciu tego podejścia, chyba że $ rodzic jest Singleton. Jeśli tak, możesz uzyskać instancję Singleton, np. Parent::getInstance(), aby osiągnąć to, co chcesz, ale pamiętaj, że Singletony nie są ulubionym wzorem dla wszystkich, np. trudne do przetestowania.

3. Zastosowanie Dziedziczenie

class B extends Parent 
{ 
    public function accessParent() 
    { 
     $this->someMethodInParent(); 
    } 
} 

W ten sposób można stworzyć oznacza związek. Wszystkie publiczne i chronione metody i właściwości z klasy nadrzędnej (ale nie określonej instancji) będą dostępne w języku B i będzie można uzyskać do nich dostęp za pomocą słowa kluczowego $this instancji B.

Dla USECASE, takie podejście nie działa, jak nie mieć wystąpienie Dominującej w ogóle, ale B by upakować wszystko rodzica, kiedy to utworzony

$b = new B; 

4. Zastosowanie globalny słów kluczowych

class B extends Parent 
{ 
    private $parent; 

    public function __construct() 
    { 
     global $parent; 
     $this->parent = $parent; 
    } 

    public function accessParent() 
    { 
     $this->parent->someMethodInParent(); 
    } 
} 

w global słów kluczowych import zmiennych globalnych do bieżącego zakresu. Ogólnie rzecz biorąc, you should avoid using the global keyword w kontekście OO, ale użyj jednej z trzech pozostałych metod powyżej, najlepiej pierwszej. Mimo że jest to funkcja językowa, jest niezadowolona - mimo że jest to kolejna pozycja najbliższa pierwszej, np.

$parent->child = new B(); 

W każdym razie, mam nadzieję, że pomaga.

+0

to jest tak dziwne – user151496

+0

Dzięki za utrzymywanie tego posta na bieżąco, Gordon. Miły. – Ricalsin

0

nr

Można uzyskać dostęp do zmiennych z nadklasy użyciu $ to:

<?php 
class A { 
    public function __construct() 
    { 
     $this->foo = 'hello'; 
    } 
} 

class B extends A { 
    public function printFoo() 
    { 
     echo $this->foo; 
    } 
} 

$b = new B(); 
$b->printFoo(); 
?> 
+0

To nie było pytanie. Nie chce uzyskać dostępu do nadklasy. – Hinek

+0

Myślę, że ta odpowiedź jest w porządku ("Nie"). Sjoerd zapewnia również alternatywne rozwiązanie. –

1

Przechodząc rodzica do dziecka jest lepszym rozwiązaniem. Chociaż jest to nieco niepożądany związek symbiotyczny.

Czy B() ma jakąkolwiek wiedzę o przedmiocie, którego jest atrybutem? Najprawdopodobniej nie. Są one luźno powiązane przez kompozycję.

Dlaczego B() musi być atrybutem jego rodzica? Czy potrzebujesz tej implementacji w B() lub czy powinna ona należeć do rodzica?

+0

Po miesiącu javascript, w którym obiekt przechodzenia jest normalny, uważam, że php jest po prostu zbyt "statyczny" w tym przypadku. Pomyśl o strukturze mvc, w której niektóre właściwości są zdefiniowane po drodze, a nie domyślnie, a na końcu główna klasa kontrolera wywołuje metodę, która uruchamia tworzenie obiektu podrzędnego. Jeśli użyję metody "rozszerzania" przez Sjoerd, nie będę mógł uzyskać dostępu do właściwości utworzonych w drodze, ale tylko do właściwości zdefiniowanych na górze klasy. – AntonioCorrenti

+0

Więc musisz omijać obiekt, który zawiera informacje, które budujesz? Może powinieneś ponownie pomyśleć o tym projekcie, aby zmniejszyć sprzężenie - czy pomocny będzie tu pojemnik wtryskowy zależności? –

0

Jestem prawie pewien, że PHP nie ma czegoś takiego.

Twoje rozwiązanie polegające na przekazaniu rodzic-obiekt dziecku jest najlepszym rozwiązaniem, jak sądzę. Powinieneś rozważyć ustawienie właściwości Parent tylko w konstruktorze dziecka, aby uniemożliwić wielu rodzicom posiadanie tego samego dziecka.

1

Może to być przydatne w niektórych przypadkach: nie spowoduje to nadania obiektowi nadrzędnemu obiektu ChildClass bardzo wcześnie w konstruktorze, ale krok później. Odgrywa ona zdolność do przechwytywania nieistniejącej metody:

class ParentClass 
{ 
    const CHILD_PROPERTY_NAME = 'child'; 
    public $data = 'Some data'; 

    public function 
    __set($property_name, $property_value) 
    { 
     if ($property_name == self::CHILD_PROPERTY_NAME) 
     { 
      $property_value->set_parent_object($this); 
     } 
    } 
} 


class ChildClass 
{ 
    private $parent_object = null; 

    public function 
    set_parent_object($object) 
    { 
     $this->parent_object = $object; 
     echo $this->parent_object->data; 
    } 

} 


$p = new ParentClass(); 
$p->child = new ChildClass(); 

Będzie to wyjście Some data

Powiązane problemy