2010-03-11 20 views
11

¿Hay alguna manera de recorrer un objeto para obtener los datos del objeto principal? Con "objeto principal" no me refiero a la clase principal, sino literalmente objeto. Aquí un ejemplo, en un mundo :-) javascripty:Objeto principal en php

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

$parent->child = new B(); 

Sería muy bueno si pudiera acceder a todos los datos de los padres en el objeto secundario:

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" 
    } 
} 

Por ahora mi solución es pasar el objeto primario al niño (como referencia) o hacer que el padre sea global. ¿Tiene alguna solución mejor?

Gracias!

+0

es sólo dos objetos con referencias a la otra. puedes llamarlos padre e hijo. – Anurag

+0

¿Por qué necesita que el niño tenga una referencia a sus padres? ¿Hay algo en el padre que el niño necesita acceso también? Si es así, es mejor que le entregues al niño todo lo que pueda necesitar en lugar de intentar obtenerlo del padre. – rojoca

+0

Tengo en el padre un "objeto de privacidad", luego algunas variables que necesito en el niño, y pasarlas a todas sería tedioso ... – AntonioCorrenti

Respuesta

21

No hay manera de invocar

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

y automáticamente tener una referencia a los padres en $ B.


En general, hay cuatro maneras de estructurar sus clases:

1. Agregue el objeto primario a través de Inyección, por ejemplo

class B 
{ 
    private $parent; 

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

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

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

Uso inyección de constructor cuando el objeto tiene que tener un padre cuando se crea. Esta es una relación has-a y crea un acoplamiento muy flexible. No hay dependencias codificadas en B, por lo que puede intercambiar fácilmente la instancia principal, por ejemplo con una simulación cuando UnitTesting. El uso de Dependency Injection hará que su código sea más fácil de mantener.

En el caso de uso, que le pasa a B $parent al crear B:

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

2.Uso Composición

class B 
{ 
    private $parent; 

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

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

Ésta es también una tiene una relación-, pero las parejas de la clase padre a B. Tampoco es una instancia de Padres existente, sino una nueva instancia. De la redacción me resulta un tanto extraño tener un padre creado por el niño. Use esto, cuando la dependencia es una clase que no se considera que existe fuera de la clase raíz, pero es parte de todo lo que representa.

Para su UseCase, no hay forma de hacer $parent->child = new B(); y saber qué padre es cuando usa este enfoque, a menos que $ parent sea Singleton. De ser así, podría obtener la instancia de Singleton, p. Parent::getInstance() para lograr lo que desea, pero tenga en cuenta que los Singletons no son el patrón favorito de todos, p. difícil de probar

3. Uso Herencia

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

De esta manera se crea un es, una relación. Todos los métodos y propiedades públicos y protegidos de la clase Parent, (pero no de una instancia específica) estarán disponibles en B y puede acceder a ellos a través de la palabra clave $this de la instancia B.

Para su USECASE, este enfoque no funciona, ya que no tiene que tener una instancia de los padres en todo, pero B sería encapsular todo de los padres cuando se crea

$b = new B; 

4. Uso de palabras clave mundial

class B extends Parent 
{ 
    private $parent; 

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

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

las importaciones de palabras clave global variables globales en el ámbito actual. En general, you should avoid using the global keyword en un contexto OO, pero utilice uno de los otros tres métodos anteriores, preferiblemente el primero. Si bien es una función de idioma, está mal visto, aunque es la siguiente más cercana a la primera, p.

$parent->child = new B(); 

De todos modos, espero que ayude.

+0

esto es tan extraño – user151496

+0

Gracias por mantener esta publicación actualizada, Gordon. Bonito. – Ricalsin

0

Puede acceder a las variables de la superclase utilizando este $:

<?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

Esta no era la pregunta. Él no quiere acceder a la superclase. – Hinek

+0

Creo que esta respuesta está bien ("No"). Sjoerd también proporciona una solución alternativa. –

1

Pasando el padre para el niño es la mejor solución. Aunque es una relación simbiótica algo indeseable.

¿Debería B() tener algún conocimiento del objeto del que es un atributo? Es más que probable que no. Estos solo están vagamente relacionados a través de la composición.

¿Por qué B() necesita ser un atributo de su padre? ¿Necesita tener esta implementación en B() o debería ser parte del padre?

+0

Después de un mes de javascript, donde el objeto transversal es normal, encuentro que php es demasiado "estático" en este caso. Piense en un marco mvc donde algunas propiedades se definen en el camino y no de forma predeterminada y al final la clase principal del controlador llama a un método que dispara una creación de objetos secundarios. Si utilizo el método "extends" de Sjoerd, no puedo acceder a las propiedades creadas en el camino, sino solo a las propiedades definidas en la parte superior de la clase. – AntonioCorrenti

+0

¿De modo que necesita pasar un objeto que contiene la información que está creando? Tal vez debería volver a pensar en este diseño para reducir el acoplamiento: ¿sería útil un contenedor de inyección de dependencia aquí? –

0

Estoy bastante seguro de que PHP no tiene algo así.

Su solución de pasar el objeto principal al niño es la mejor solución, creo. Debería considerar establecer su propiedad principal solo en el constructor del hijo para evitar que varios padres tengan el mismo hijo.

1

Tal vez pueda ser útil en algunos casos: no trae objetos principales a ChildClass muy temprano en el constructor, pero un paso más adelante. Se juega con capacidad de interceptar método no-existente:

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(); 

Esta es la salida Some data