extender clase en diferentes archivos.

991 views
Skip to first unread message

diego

unread,
May 26, 2013, 2:08:22 AM5/26/13
to php...@googlegroups.com
hola a todos. estoy adentrandome en el OOP
y quiero extender una clase desde otro archivo.
como tengo que hacerlo? me estoy complicando la vida con los require_once

padre.php
-----------------
<?php
class Padre {
...
}

hijo.php
-----------------
<?php
class Hijo extends Padre {
   var $nombre;

   function inscribir($nom){
      $this->nombre = $nom;
   }
}

index.php
-----------------
<?php
include('padre.php')
$padre = new Padre;
$hijo = $padre->Hijo->inscribir('jose');

saludos y buenas noches

diego

Tordek

unread,
May 26, 2013, 6:42:01 AM5/26/13
to php...@googlegroups.com
On 26/05/13 03:08, diego wrote:

> /index.php/
> /-----------------/
> <?php
> include('padre.php')
> $padre = new Padre;
> $hijo = $padre->Hijo->inscribir('jose');

Creo que ten�s un concepto equivocado de lo que hac�s con extensi�n;
eso, o est�s tirando c�digo y esperando que algo funcione.

Cuando vos dec�s que Hijo extiende a Padre, est�s diciendo que Hijo
tiene todo lo que tiene Padre, pero con cosas modificadas o agregadas.

Pod�s instanciar un padre o un hijo, o usar un hijo donde se te pida
un padre, y tratar a un hijo como si fuera un padre (esto es el
principio de sustituci�n de Liskov); pero no pod�s tratar a un padre
como si fuera un hijo.

Tu index.php podr�a ser:

<?php
include('padre.php');
include('hijo.php');
$hijo = new Hijo();
$hijo->inscribir('jose');

si lo que quer�s es extender.

En cambio, si lo que quer�as era que un padre tenga un hijo de tipo
Hijo, necesit�s algo como

<?php
include('padre.php');
include('hijo.php');
$padre = new Padre();
$padre->hijo = new Hijo();

.

No s� cual es el caso que est�s buscando hacer, porque tu ejemplo es
demasiado corto (y ambiguo) para decirlo a ciencia cierta.

==

Por otro lado, tratar de hacer cualquier tipo de OO en PHP se va a
volver una mara�a de includes y requires, adem�s de obligarte
innecesariamente a saber d�nde definiste cada archivo.

Lo mejor que pod�s hacer es usar spl_autoload_register, que define
una funci�n que le indica a PHP d�nde buscar los archivos de clase
para las clases que no conoce.

En su forma m�s b�sica, simplemente us�s


==
<?php

spl_autoload_register();

$hijo = new Hijo();
==

y si orden�s tus archivos apropiadamente, PHP los encuentra solo.
Para eso necesit�s definir, por ejemplo, `class Hijo extends Padre`
en `Hijo.php`, y `class Padre` en `Padre.php`.

Para casos m�s complejos (con namespaces y librer�as ajenas) mir�
los detalles del PSR-0.

Asegurate siempre de seguir los est�ndares de PSR-0. Incluso si no
concord�s con los dem�s (reglas sobre d�nde poner las llaves, c�mo
indentar, etc.), el PSR-0 te dice c�mo ordenar los archivos.

http://www.php-fig.org/psr/0/
http://www.php-fig.org/psr/1/
http://www.php-fig.org/psr/2/
http://www.php-fig.org/psr/3/


>
> saludos y buenas noches
>
> diego


--
Guillermo O. �Tordek� Freschi. Programador, Escritor, Genio Maligno.
http://tordek.com.ar :: http://twitter.com/tordek

diego

unread,
May 26, 2013, 4:25:08 PM5/26/13
to php...@googlegroups.com
hola. gracias por tu respuesta.
he visto en frameworks como codeigniter por ej. supongo que todos son iguales
donde hay clases que extienden a una clase principal,
pero para poder utilizarla primero hay que inicializar la clase principal (aunque se inicializar solo)
ej claseprincipal->clasequehereda->metodo()

entonces este metodo() puede acceder tambien a otros metodos de otra clase o de la clase principal
el caso es por ej. dentro de un controlador se pueden acceder a librerias (que son clases) por ej url, input, basededatos, etc, etc.
podria mostrarme un ejemplo super simple de esto para poder comprenderlo mejor?
gracias!

diego


2013/5/26 Tordek <ked...@gmail.com>
On 26/05/13 03:08, diego wrote:

/index.php/
/-----------------/

<?php
include('padre.php')
$padre = new Padre;
$hijo = $padre->Hijo->inscribir('jose');

Creo que tenés un concepto equivocado de lo que hacés con extensión; eso, o estás tirando código y esperando que algo funcione.

Cuando vos decís que Hijo extiende a Padre, estás diciendo que Hijo tiene todo lo que tiene Padre, pero con cosas modificadas o agregadas.

Podés instanciar un padre o un hijo, o usar un hijo donde se te pida un padre, y tratar a un hijo como si fuera un padre (esto es el principio de sustitución de Liskov); pero no podés tratar a un padre como si fuera un hijo.

Tu index.php podría ser:


<?php
include('padre.php');
include('hijo.php');
$hijo = new Hijo();
$hijo->inscribir('jose');

si lo que querés es extender.

En cambio, si lo que querías era que un padre tenga un hijo de tipo Hijo, necesitás algo como


<?php
include('padre.php');
include('hijo.php');
$padre = new Padre();
$padre->hijo = new Hijo();

.

No sé cual es el caso que estás buscando hacer, porque tu ejemplo es demasiado corto (y ambiguo) para decirlo a ciencia cierta.

==

Por otro lado, tratar de hacer cualquier tipo de OO en PHP se va a volver una maraña de includes y requires, además de obligarte innecesariamente a saber dónde definiste cada archivo.

Lo mejor que podés hacer es usar spl_autoload_register, que define una función que le indica a PHP dónde buscar los archivos de clase para las clases que no conoce.

En su forma más básica, simplemente usás



==
<?php

spl_autoload_register();

$hijo = new Hijo();
==

y si ordenás tus archivos apropiadamente, PHP los encuentra solo. Para eso necesitás definir, por ejemplo, `class Hijo extends Padre` en `Hijo.php`, y `class Padre` en `Padre.php`.

Para casos más complejos (con namespaces y librerías ajenas) mirá los detalles del PSR-0.

Asegurate siempre de seguir los estándares de PSR-0. Incluso si no concordás con los demás (reglas sobre dónde poner las llaves, cómo indentar, etc.), el PSR-0 te dice cómo ordenar los archivos.
--
Guillermo O. «Tordek» Freschi. Programador, Escritor, Genio Maligno.
http://tordek.com.ar :: http://twitter.com/tordek

--
Has recibido este mensaje porque estás suscrito al grupo "Grupo PHP Argentina" de Grupos de Google.
Para anular la suscripción a este grupo y dejar de recibir sus correos electrónicos, envía un correo electrónico a php-arg+unsubscribe@googlegroups.com.
Para publicar una entrada en este grupo, envía un correo electrónico a php...@googlegroups.com.
Visita este grupo en http://groups.google.com/group/php-arg?hl=es.
Para obtener más opciones, visita https://groups.google.com/groups/opt_out.



Tordek

unread,
May 26, 2013, 5:52:26 PM5/26/13
to php...@googlegroups.com
On 26/05/13 17:25, diego wrote:
> he visto en frameworks como codeigniter por ej. supongo que todos
> son iguales

Ni tanto.

> donde hay clases que extienden a una clase principal,
> pero para poder utilizarla primero hay que inicializar la clase
> principal (aunque se inicializar solo)

> ej claseprincipal->clasequehereda->metodo()

Esta sintaxis no funciona como pens�s: Las clases padre no conocen a
sus hijas (imaginate que eso significar�a cargar absolutamente todos
los archivos para ver cuales tienen clases que heredan de tu clase!).

Si vos dec�s cosas como

$this->load->view();

es porque load es una propiedad de $this.

Si yo tengo una clase Persona que tiene un nombre, yo pongo:

class Persona {
private $nombre;
}

y hago

$unaPersona = new Persona();
$unaPersona->nombre = "Juan";

Estoy accediendo a la propiedad 'nombre' de la instancia que cre�.

Es decir, el framework hace algo como

$controller = new Pages();

$controller->load = new Load();

y Load es una clase que define un m�todo view();.

Pod�s ver el c�digo de CI directamente:

https://github.com/EllisLab/CodeIgniter/blob/develop/system/core/Controller.php

en __construct() de Controller, hace

$this->load =& load_class('Loader', 'core');

donde load_class es la forma que usa CodeIgniter para instanciar un
singleton.
.

> entonces este metodo() puede acceder tambien a otros metodos de otra
> clase o de la clase principal

Para hacer esto, una forma ser�a instanciar el controlador de esta
manera:

$controller = new Pages();

$controller->load = new Load($controller);

Entonces tu Load() podr�a ser

class Load() {
private $controller;
function __construct($cont) {
$controller = $cont;
}

function template($name) {
$controller->addTemplate($name);
}
}

As� ten�s que la clase Load guarda una referencia al controlador,
entonces puede llamar a m�todos del controlador. Esto no lo ves en
CodeIgniter porque todo lo instancia como singleton.

diego

unread,
May 27, 2013, 2:20:48 PM5/27/13
to php...@googlegroups.com
buenisimo me aclaraste varias dudas. voy a armar algo asi pongo en practica esto y cualquier cosa vuelvo.
gracias!

diego


2013/5/26 Tordek <ked...@gmail.com>
On 26/05/13 17:25, diego wrote:

he visto en frameworks como codeigniter por ej. supongo que todos
son iguales

Ni tanto.


donde hay clases que extienden a una clase principal,
pero para poder utilizarla primero hay que inicializar la clase
principal (aunque se inicializar solo)

ej claseprincipal->clasequehereda->metodo()

Esta sintaxis no funciona como pensás: Las clases padre no conocen a sus hijas (imaginate que eso significaría cargar absolutamente todos los archivos para ver cuales tienen clases que heredan de tu clase!).

Si vos decís cosas como


$this->load->view();

es porque load es una propiedad de $this.

Si yo tengo una clase Persona que tiene un nombre, yo pongo:

class Persona {
    private $nombre;
}

y hago

$unaPersona = new Persona();
$unaPersona->nombre = "Juan";

Estoy accediendo a la propiedad 'nombre' de la instancia que creé.


Es decir, el framework hace algo como

$controller = new Pages();

$controller->load = new Load();

y Load es una clase que define un método view();.

Podés ver el código de CI directamente:


https://github.com/EllisLab/CodeIgniter/blob/develop/system/core/Controller.php

en __construct() de Controller, hace

$this->load =& load_class('Loader', 'core');

donde load_class es la forma que usa CodeIgniter para instanciar un singleton.

.

entonces este metodo() puede acceder tambien a otros metodos de otra
clase o de la clase principal

Para hacer esto, una forma sería instanciar el controlador de esta manera:


$controller = new Pages();

$controller->load = new Load($controller);

Entonces tu Load() podría ser


class Load() {
   private $controller;
   function __construct($cont) {
       $controller = $cont;
   }

   function template($name) {
       $controller->addTemplate($name);
   }
}

Así tenés que la clase Load guarda una referencia al controlador, entonces puede llamar a métodos del controlador. Esto no lo ves en CodeIgniter porque todo lo instancia como singleton.


diego


--
Guillermo O. «Tordek» Freschi. Programador, Escritor, Genio Maligno.
http://tordek.com.ar :: http://twitter.com/tordek

Reply all
Reply to author
Forward
0 new messages