Foros del Web » Programando para Internet » PHP »

[SOLUCIONADO] PHP hardcodea __construct() y clone() .. por que ?

Estas en el tema de PHP hardcodea __construct() y clone() .. por que ? en el foro de PHP en Foros del Web. Haciendo experimentos... acabo de caer en cuentas de porque perdi como 3 horas hoy tratando de crea un objeto como clase derivada en runtime pero ...
  #1 (permalink)  
Antiguo 29/05/2014, 15:39
Avatar de Italico76  
Fecha de Ingreso: abril-2007
Mensajes: 3.303
Antigüedad: 17 años, 1 mes
Puntos: 292
Exclamación PHP hardcodea __construct() y clone() .. por que ?

Haciendo experimentos... acabo de caer en cuentas de porque perdi como 3 horas hoy tratando de crea un objeto como clase derivada en runtime pero desde el constructor y luego con clone() y siempre con resultados inesperados

Código PHP:
Ver original
  1. <?php
  2.  
  3. Class Foo
  4. {
  5.     public $bar="Bar"; 
  6.    
  7.     public function __construct()
  8.     {
  9.         // aca no funciona, esta hardcodeada la devolucion a $this
  10.         return new StdClass;
  11.     }
  12.    
  13.     public function __clone()
  14.     {
  15.         // aca no funciona, esta hardcodeada la devolucion a $this
  16.         return new StdClass;
  17.     }
  18.    
  19.     // aca si
  20.     public function getInstance()
  21.     {      
  22.         return new StdClass;
  23.     }
  24.    
  25. }
  26.  
  27. $foo = new Foo;
  28. var_dump ($foo);
  29. var_dump(clone $foo);
  30. var_dump ($foo->getInstance());

Arroja:

Cita:
Foo Object
(
[bar] => Bar
)
Foo Object
(
[bar] => Bar
)
stdClass Object
(
)
Alguna idea de porque me quieren complicar la vida ?
__________________
Salu2!
  #2 (permalink)  
Antiguo 29/05/2014, 15:56
Avatar de pateketrueke
Modernizr
 
Fecha de Ingreso: abril-2008
Ubicación: Mexihco-Tenochtitlan
Mensajes: 26.399
Antigüedad: 16 años
Puntos: 2534
Respuesta: PHP hardcodea __construct() y clone() .. por que ?

Un constructor jamás podrá devolver una instancia ajena.

Es decir, ¿para qué usas clases si piensas devolver un objeto que no representa a la clase?
__________________
Y U NO RTFM? щ(ºдºщ)

No atiendo por MP nada que no sea personal.
  #3 (permalink)  
Antiguo 29/05/2014, 16:29
Avatar de Italico76  
Fecha de Ingreso: abril-2007
Mensajes: 3.303
Antigüedad: 17 años, 1 mes
Puntos: 292
Respuesta: PHP hardcodea __construct() y clone() .. por que ?

Cita:
Iniciado por pateketrueke Ver Mensaje
Un constructor jamás podrá devolver una instancia ajena.

Es decir, ¿para qué usas clases si piensas devolver un objeto que no representa a la clase?
Bueno, necesito crear en runtime una clase derivada, esa parte la tengo facil con eval() pero luego quisiera devolverla de una vez o sea que el objeto creado sea una instancia de una clase derivada (especificamente porque quiero cambiarle la firma de "tipo" en runtime a la padre y eso no es posible)

Creo me devolvere sobre mis pasos.... y hare una clase estatica que cree los objetos que necesito, es mas económico y de todas formas no puedo ocupar ni el __construct() ni clone() asi que ni modo


Creeria que PHP podria tener en cuenta que estoy devolviendo un objeto y no sobre-escribir mi devolucion pero seguramente seria "transgiversar" el objetivo de un constructor... algo asi como lo que tu dices.

Gracias amigo
__________________
Salu2!
  #4 (permalink)  
Antiguo 29/05/2014, 16:40
Avatar de pateketrueke
Modernizr
 
Fecha de Ingreso: abril-2008
Ubicación: Mexihco-Tenochtitlan
Mensajes: 26.399
Antigüedad: 16 años
Puntos: 2534
Respuesta: PHP hardcodea __construct() y clone() .. por que ?

Pues sí, ahí necesitas implementar el patrón Factory, y ni siquiera necesitas usar clases para eso.

Al final un método estático no es más que una función sin estado.
__________________
Y U NO RTFM? щ(ºдºщ)

No atiendo por MP nada que no sea personal.
  #5 (permalink)  
Antiguo 29/05/2014, 17:50
Avatar de hhs
hhs
Colaborador
 
Fecha de Ingreso: junio-2013
Ubicación: México
Mensajes: 2.995
Antigüedad: 10 años, 10 meses
Puntos: 379
Respuesta: PHP hardcodea __construct() y clone() .. por que ?

Cita:
Creeria que PHP podria tener en cuenta que estoy devolviendo un objeto y no sobre-escribir mi devolucion pero seguramente seria "transgiversar" el objetivo de un constructor... algo asi como lo que tu dices.
Precisamente para eso es el polimorfismo y el principio de sustitución de liskov: para que puedas usar los objetos de forma intercambiable.
__________________
Saludos
About me
Laraveles
A class should have only one reason to change.
  #6 (permalink)  
Antiguo 29/05/2014, 18:51
Avatar de NSD
NSD
Colaborador
 
Fecha de Ingreso: mayo-2012
Ubicación: Somewhere
Mensajes: 1.332
Antigüedad: 12 años
Puntos: 320
Respuesta: PHP hardcodea __construct() y clone() .. por que ?

Tanto el constructor, como el destructor y clone, no retornan nada (void):
http://www.php.net/manual/es/language.oop5.decon.php
http://www.php.net/manual/es/languag...p#object.clone
new y clone son construcciones del lenguaje y los metodos respectivos no son mas que unos callbacks posteriores a la creacion/clonacion del objeto, php ya sabe lo que va a retornar antes de ejecutar el metodo, la prueba esta en que la variable $this esta disponible, y esta no es modificable en ningun momento, hacerlo produce un error fatal y bla bla bla.

__construct, __destruct y __clone no son como los metodos magicos (http://www.php.net/manual/es/language.oop5.magic.php) si bien el contenido de return es evaluado, la respuesta es void.

No obstante, puedes hacer esto como una alternativa para lograr un efecto similar:
Código PHP:
Ver original
  1. $foo = (new Foo)->getInstance();
__________________
Maratón de desafíos PHP Junio - Agosto 2015 en FDW | Reglamento - Desafios
  #7 (permalink)  
Antiguo 30/05/2014, 08:29
lolainas
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: PHP hardcodea __construct() y clone() .. por que ?

Esto podrías hacer:

Código PHP:
Ver original
  1. class Padre {
  2.    
  3.     function __construct() {
  4.         return new DateTime;
  5.     }
  6.    
  7.     function __clone() {
  8.         return new DOMDocument;
  9.     }
  10.    
  11. }
  12.  
  13. class Hijo extends Padre {
  14.    
  15.     function __construct() {
  16.         var_dump(__METHOD__, parent::__construct());
  17.     }
  18.    
  19.     function __clone() {
  20.         var_dump(__METHOD__, parent::__clone());
  21.     }
  22.    
  23. }
  24.  
  25. clone new Hijo;

Según parece, sólo podrías captar ese valor desde una clase hija, en la última hija ya nunca más podrías recuperar ese valor desde fuera.
  #8 (permalink)  
Antiguo 30/05/2014, 08:47
Avatar de Italico76  
Fecha de Ingreso: abril-2007
Mensajes: 3.303
Antigüedad: 17 años, 1 mes
Puntos: 292
Respuesta: PHP hardcodea __construct() y clone() .. por que ?

Ya, ...

Código PHP:
Ver original
  1. $this = new StdClass;

Lo anterior tampoco funciona, $this es una propiedad readonly que solo devuelve un puntero al espacio local.


En otros lenguajes como Javascritpt o Python se puede sobre-escribir una funcion / metodo / clase pero en PHP no, si se pudiera seria una salida pero como dice @pateketrueke para eso hay un patron que lo resuelve.


Curiosamente... esto tampoco funciona, no da error ni funciona:

Código PHP:
Ver original
  1. Class Bar
  2. { }
  3.  
  4. Class Foo
  5. {
  6.        
  7.     public function __construct()
  8.     {
  9.         global $foo;
  10.         $foo = new Bar;        
  11.     }  
  12. }
  13.  
  14.  
  15.  
  16. $foo = new Foo;
  17. debug ($foo);
  18. debug ($foo); // tampoco ahora :)

Esperaria que la segunda vez al menos fuera de tipo 'Bar' pero no... sigue siendo 'Foo object'
__________________
Salu2!

Última edición por Italico76; 30/05/2014 a las 08:58
  #9 (permalink)  
Antiguo 31/05/2014, 12:59
Avatar de NSD
NSD
Colaborador
 
Fecha de Ingreso: mayo-2012
Ubicación: Somewhere
Mensajes: 1.332
Antigüedad: 12 años
Puntos: 320
Respuesta: PHP hardcodea __construct() y clone() .. por que ?

Código PHP:
Ver original
  1. Class Bar { }
  2.  
  3. Class Foo
  4. {
  5.        
  6.     public function __construct()
  7.     {
  8.         global $foo;
  9.         $foo = new Bar;        
  10.     }  
  11. }
  12.  
  13.  
  14.  
  15. $foo = new Foo;
  16. debug ($foo);
  17. debug ($foo); // tampoco ahora :)

Veamos lo que hace ese codigo:

1) $foo = new Foo;

es equivalente a:

1.a) $foo = (new Foo);

por lo tanto $foo sufre estos cambios:

1) $foo = undefined (que no esta seteada)
2) Primero se resuelve la llamada al constructor de Foo
2.a) Se declara a $foo como global, como no esta definida, se le asigna null.
2.b) $foo = null;
2.c) El constructor setea la variable global con una instancia de Bar
2.d) $foo = new Bar;
3) Ahora, se resulve la igualdad, como el constructor devuelve una instancia del objeto Foo, entonces
3.a) $foo = new Foo

Se entiende porque no funciona? la asignacion esta pisando la instancia de Bar que tu asignas manualmente.

Ahora, para esto hay alternativas, la primera:

Código PHP:
Ver original
  1. <?php
  2. Class Bar { }
  3. Class Foo
  4. {        
  5.     public function __construct()
  6.     {
  7.         global $foo;
  8.         var_dump($foo);
  9.         $foo = new Bar;
  10.         var_dump($foo);        
  11.     }  
  12. }
  13. new Foo;
  14. var_dump($foo);  
  15.  
  16. //null
  17. //object(Bar)[2]
  18. //object(Bar)[2]

lo cual esta bien, perooooo, estas atado a la variable $foo, entonces, generalizando:


Código PHP:
Ver original
  1. <?php
  2. Class Bar { }
  3. Class Foo
  4. {        
  5.     public function __construct(&$foo)
  6.     {
  7.         var_dump($foo);
  8.         $foo = new Bar;
  9.         var_dump($foo);        
  10.     }  
  11. }
  12. new Foo($foo);
  13. var_dump($foo);  
  14.  
  15. //null
  16. //object(Bar)[2]
  17. //object(Bar)[2]

tienes un efecto similar
__________________
Maratón de desafíos PHP Junio - Agosto 2015 en FDW | Reglamento - Desafios
  #10 (permalink)  
Antiguo 31/05/2014, 15:00
Avatar de Italico76  
Fecha de Ingreso: abril-2007
Mensajes: 3.303
Antigüedad: 17 años, 1 mes
Puntos: 292
Respuesta: PHP hardcodea __construct() y clone() .. por que ?

@NSD : excelente analisis y resolucion del problema !

Que pesar que "new Foo($foo);" no sea una forma muy estandar de instanciar un objeto y por tanto no la veo para un proyecto donde terceros deban utilizar una clase con esta implementacion :-\
__________________
Salu2!
  #11 (permalink)  
Antiguo 31/05/2014, 15:21
Avatar de NSD
NSD
Colaborador
 
Fecha de Ingreso: mayo-2012
Ubicación: Somewhere
Mensajes: 1.332
Antigüedad: 12 años
Puntos: 320
Respuesta: PHP hardcodea __construct() y clone() .. por que ?

Cita:
Que pesar que "new Foo($foo);" no sea una forma muy estandar de instanciar un objeto y por tanto no la veo para un proyecto donde terceros deban utilizar una clase
Desde el punto de vista practico, tienes toda la razon.
Desde el punto de vista teorico, estaria bueno hacer unos benchmarks y ver que es mas eficiente, si esta implementacion, la asignacion tradicional, o una factoria, como para dar un ultimo punto de vista al tema solo por curiosidad, mas alla de que lo que dices es totalmente razonable.
__________________
Maratón de desafíos PHP Junio - Agosto 2015 en FDW | Reglamento - Desafios
  #12 (permalink)  
Antiguo 01/06/2014, 16:52
Avatar de hhs
hhs
Colaborador
 
Fecha de Ingreso: junio-2013
Ubicación: México
Mensajes: 2.995
Antigüedad: 10 años, 10 meses
Puntos: 379
Respuesta: PHP hardcodea __construct() y clone() .. por que ?

Buen análisis NSD.
No seria útil desde el punto de vista de diseño, ya que Foo tiene que conocer a Bar para crear la instancia y eso crea acoplamiento. Ademas de que estas violando el encapsulamiento al manejar la asignación fuera de la clase.
En cuanto a eficiencia no debe de haber mucha diferencia entre las tres opciones, con el valor agregado de que los patrones de creación son mas flexibles.
__________________
Saludos
About me
Laraveles
A class should have only one reason to change.
  #13 (permalink)  
Antiguo 01/06/2014, 18:10
Avatar de NSD
NSD
Colaborador
 
Fecha de Ingreso: mayo-2012
Ubicación: Somewhere
Mensajes: 1.332
Antigüedad: 12 años
Puntos: 320
Respuesta: PHP hardcodea __construct() y clone() .. por que ?

Por si les interesa, comparto los resultados de un benchmarck por los seis métodos, asignación directa, utilización de new con parámetro referenciado, factoría estática con return y factoría estática con parámetro referenciado, funcion comun con return, funcion comun con parametro referenciado.

El código esta aquí para que puedan replicar cómodamente la prueba: https://eval.in/157663

Y los resultados son estos:
Cita:
$foo = new Bar(); 0.00042104721069335938
new Foo($foo); 0.00061511993408203125
$foo = Factory::getBar(); 0.00041198730468750000
Factory::setBar($foo); 0.00048804283142089844
$foo = getBar(); 0.00042486190795898438
setBar($foo); 0.00047302246093750000
No voy a hacer un análisis, como diría cierto reggaetonero "Los números hablan por si solos"
__________________
Maratón de desafíos PHP Junio - Agosto 2015 en FDW | Reglamento - Desafios
  #14 (permalink)  
Antiguo 23/06/2014, 17:05
Avatar de NSD
NSD
Colaborador
 
Fecha de Ingreso: mayo-2012
Ubicación: Somewhere
Mensajes: 1.332
Antigüedad: 12 años
Puntos: 320
Respuesta: PHP hardcodea __construct() y clone() .. por que ?

Revivo este tema ya que existe otra forma diferente de lograr el efecto buscado que no esta expuesta:
Código PHP:
Ver original
  1. <?php
  2.     class foo
  3.     {
  4.    
  5.     }
  6.    
  7.     $class = "foo";
  8.    
  9.     $foo = new $class;
  10.    
  11.     var_dump($foo); // object(foo)[1]

La pongo solo como curiosidad, la flexibilidad de PHP es muy grande.
__________________
Maratón de desafíos PHP Junio - Agosto 2015 en FDW | Reglamento - Desafios
  #15 (permalink)  
Antiguo 23/06/2014, 17:48
Avatar de hhs
hhs
Colaborador
 
Fecha de Ingreso: junio-2013
Ubicación: México
Mensajes: 2.995
Antigüedad: 10 años, 10 meses
Puntos: 379
Respuesta: PHP hardcodea __construct() y clone() .. por que ?

viene documentada en el manual: http://www.php.net/manual/en/languag...oop5.basic.new
__________________
Saludos
About me
Laraveles
A class should have only one reason to change.
  #16 (permalink)  
Antiguo 23/06/2014, 20:44
Avatar de NSD
NSD
Colaborador
 
Fecha de Ingreso: mayo-2012
Ubicación: Somewhere
Mensajes: 1.332
Antigüedad: 12 años
Puntos: 320
Respuesta: PHP hardcodea __construct() y clone() .. por que ?

@hhs tienes razon, no me habia percatado, bueno entonces aca va otra opcion usando constantes:
Código PHP:
Ver original
  1. <?php
  2.     define("actFoo", "foo");
  3.    
  4.     class foo
  5.     {
  6.     }    
  7.    
  8.     $foo = new ${${constant('actFoo')} = constant('actFoo')};
  9.    
  10.     var_dump($foo);

de todas las expuestas, es sin duda, la mas rebuscada.
__________________
Maratón de desafíos PHP Junio - Agosto 2015 en FDW | Reglamento - Desafios

Etiquetas: Ninguno
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 14:38.