Foros del Web » Programando para Internet » PHP » Frameworks y PHP orientado a objetos »

LLamar a metodo abuelo.

Estas en el tema de LLamar a metodo abuelo. en el foro de Frameworks y PHP orientado a objetos en Foros del Web. Tenemos una discusión con un compañero de trabajo, y estamos buscándole el pelo al huevo. Básicamente debemos resolver un dilema conceptual al redefinir un método ...
  #1 (permalink)  
Antiguo 31/07/2008, 17:25
Avatar de Calisco  
Fecha de Ingreso: marzo-2004
Ubicación: Neuquen
Mensajes: 732
Antigüedad: 20 años, 1 mes
Puntos: 4
LLamar a metodo abuelo.

Tenemos una discusión con un compañero de trabajo, y estamos buscándole el pelo al huevo.
Básicamente debemos resolver un dilema conceptual al redefinir un método de una clase nieta.
Supongamos ...
Código PHP:
// clase Abuelo
class {
    public function 
miMetodo () {
        
    }
}

class 
extends {
    public function 
miMetodo () {
    
/*
    Código que define el comportamiento del método antes de invocar al método padre.
    */

    // Llamamos metodo padre (A)
    
parent::miMetodo();
    }
}

class 
extends {
    public function 
miMetodo () {
    
/*
    Código que define el comportamiento del método antes de invocar al método padre.
    */

    // Llamamos metodo padre (B)
    
parent::miMetodo();
    }

Nuestro objeto se instancia de la clase C.

Analizando la naturaleza de nuestra aplicación cada uno ha propuesto una solción para resolver nuestro problema.

La primera es justamente invocar al metodo abuelo (clase A) miMetodo() desde la clase C salteando la definición del método padre (clase B) ya que, a causa de otras modificaciones necesarias en otros métodos de la clase, este código afecta en un 100% al buen funcionamiento de la aplicación. O sea, no funca.
Código PHP:
class extends {
    public function 
miMetodo ($condicion true) {

    
/*
    Código que define el comportamiento del método antes de invocar al método padre.
    */
    // Llamamos metodo abuelo (A)
    
A::miMetodo();
    }

La segunda solución al problema propone añadir un parámetro al método miMetodo () redefinido en la clase C. Sería algo como ...
Código PHP:
class extends {
    
    public function 
miMetodo ($condicion true) {

    
/*
    Código que define el comportamiento del método antes de invocar al método padre.
    */
    // Agregamos comportamiento condicional en función del nuevo parámetro $condicion agregado por primera vez en esta clase C
        
if ($condicion) ...
        else ...

    
// Llamamos metodo padre (C)
    
parent::miMetodo();
    }

Nos gustaría saber que opinan de ambos casos. Por un lado tenemos la posibilidad de saltar el método padre yendo directamente al método abuelo. Esto implica que en la definición del método se debe programar la funcionalidad correcta del método padre.

Y por otro lado la inclusión de un parámetro en la re definición del método y no saltear el método padre.

Hay varias cosas más que nos obligan a definir este comportamiento; por ejemplo, y algo muy importante, no podemos tocar ni la clase A ni la B. Si prestamos atención, en ninguno de los dos casos hacemos esto.

En fin ... saludos. Pregunen todo lo que quieran.
__________________
| Cabeza De Raton |
  #2 (permalink)  
Antiguo 31/07/2008, 17:57
Avatar de enriqueplace  
Fecha de Ingreso: mayo-2005
Ubicación: Uruguay / Argentina
Mensajes: 1.102
Antigüedad: 19 años
Puntos: 32
Respuesta: LLamar a metodo abuelo.

¿y la pregunta concreta es?

Estimados, por favor, describan claramente el escenario, luego cual es el problema y finalmente lo que han intentado.

No me queda muy claro qué problema tienen, si tienen que modificar un método "hijo" pero no quieren perder la funcionalidad del padre, etc, etc.

Nota importante: considero que ayudaría bastante "contextualizar", es decir, hablar de A, B y C es muy frio y lleva a errores muy graves, cualquier diseño está atado a un contexto, y si los objetos son representaciones de la realidad... que realidad es esa?

PD: he visto diseños que empiezan con una clase "Clases", luego una que hereda de esa que se llama "General", posteriormente una que hereda de la otra que dice "Db" (para obtener una conexión a la base de datos) y así sigue.

Y la "relación de uso" no existe.

No se hereda para reusar, no se hereda porque quede cómodo, no se hereda por heredar.

Si no hay relación de parentesco, NO SE HEREDA, y para eso hay que definir contexto y sus actores.

¿Fui claro?
__________________
Blog phpsenior.com Cursos a Distancia surforce.com
  #3 (permalink)  
Antiguo 01/08/2008, 05:07
Avatar de Calisco  
Fecha de Ingreso: marzo-2004
Ubicación: Neuquen
Mensajes: 732
Antigüedad: 20 años, 1 mes
Puntos: 4
Respuesta: LLamar a metodo abuelo.

Fuiste claro pero no contundente. Casi tan ambiguo como nosotros.
Sabemos lo que es heredar y los conocimiento mínimos como para saber cuando y cuendo no hacerlo. Sucede que queremos simplicar al máximo el marco.
A ti te dicen ...

-mira Enrique, tienes que hacer una nueva clase, que sin lugar a dudas la debes heredar de B porque en esta están todas las funcionalidades que necesitas. Pero en un método llamado miMetodo() de la nueva clase C tienes que, o bien redefinirlo en un 100% y llamar al método abuelo (clase A); o puedes redefinir miMetodo agregando un parámetro que de alguna manera te ayuda a reacomodar el funcionamiento para que ahora si, su método padre (clase B) pueda ejecutarse en forma correcta..

No puedes tocar la clase A ni la B.

Si quieres, yo me explayo al máximo. Por lo pronto solo comento que estamos trabajando con Symfony v1.0 y estamos heredando una clase de un plugIn que se utiliza para la administración de usuarios.

Explayarnos sobre el marco sería, creo, enredar más un tema que ya desde si inicio resulta complicado de explicar claramente.

Saludos.
__________________
| Cabeza De Raton |
  #4 (permalink)  
Antiguo 01/08/2008, 06:49
Avatar de enriqueplace  
Fecha de Ingreso: mayo-2005
Ubicación: Uruguay / Argentina
Mensajes: 1.102
Antigüedad: 19 años
Puntos: 32
Respuesta: LLamar a metodo abuelo.

Mis comentarios son tan ambiguos como el problema, no así la explicación conceptual que es bien concreta.

Muy probablemente el diseño esté mal, por eso están en esta situación.

De forma genérica, si no se puede tocar ni A ni B, solo te queda

1) implementar una clase C, redefinir el método y llamar al padre, o sea B.
2) implementar una clase C, heredar de A, y reimplementar lo que hacía en B.
3) y alguna variante más

No creo que se pueda hacer un diseño particular a partir de la información compartida.
__________________
Blog phpsenior.com Cursos a Distancia surforce.com
  #5 (permalink)  
Antiguo 01/08/2008, 07:13
Avatar de Calisco  
Fecha de Ingreso: marzo-2004
Ubicación: Neuquen
Mensajes: 732
Antigüedad: 20 años, 1 mes
Puntos: 4
Respuesta: LLamar a metodo abuelo.

COmo variante mas ...
3) implementar una clase C, redefinir el método y llamar al abuelo, o sea A.
__________________
| Cabeza De Raton |
  #6 (permalink)  
Antiguo 01/08/2008, 07:17
Avatar de enriqueplace  
Fecha de Ingreso: mayo-2005
Ubicación: Uruguay / Argentina
Mensajes: 1.102
Antigüedad: 19 años
Puntos: 32
Respuesta: LLamar a metodo abuelo.

Cita:
Iniciado por Calisco Ver Mensaje
COmo variante mas ...
3) implementar una clase C, redefinir el método y llamar al abuelo, o sea A.
¿Me imagino que si dices "llamar al abuelo" es una "relación de uso" y no "herencia"?
__________________
Blog phpsenior.com Cursos a Distancia surforce.com
  #7 (permalink)  
Antiguo 01/08/2008, 08:10
Avatar de Calisco  
Fecha de Ingreso: marzo-2004
Ubicación: Neuquen
Mensajes: 732
Antigüedad: 20 años, 1 mes
Puntos: 4
Respuesta: LLamar a metodo abuelo.

exacto, se hace A::miMetodo().
__________________
| Cabeza De Raton |
  #8 (permalink)  
Antiguo 01/08/2008, 08:18
Avatar de enriqueplace  
Fecha de Ingreso: mayo-2005
Ubicación: Uruguay / Argentina
Mensajes: 1.102
Antigüedad: 19 años
Puntos: 32
Respuesta: LLamar a metodo abuelo.

Entonces el diseño es muy flojo o lo son sus conceptos, la herencia no cambia por relación de uso así nomás, porque te quede cómodo.

O sea hace herencia o relación de uso, por tema de diseño y contexto, comentario que hice desde el principio.

Cliente hereda de Persona, pero no porque quede cómodo podemos hacer que Cliente use a una Persona, se distorsiona el diseño.

El diseño está mal, no es intercambiable.
__________________
Blog phpsenior.com Cursos a Distancia surforce.com
  #9 (permalink)  
Antiguo 01/08/2008, 08:33
Avatar de Calisco  
Fecha de Ingreso: marzo-2004
Ubicación: Neuquen
Mensajes: 732
Antigüedad: 20 años, 1 mes
Puntos: 4
Respuesta: LLamar a metodo abuelo.

Claro. Pero la realidad es que tenemos una parte del diseño implementada, y nos guste o no, no la podemos cambiar. Partamos de estas condiciones iniciales. Las fichas están en posición, y agarramos el tablero en el medio juego.
Frente a esta maldita condiciones, y analizando ya las particularidades de la aplicación, pudimos parchar un agujero de dos formas. Una es saltando por referencia al metodo abuelo (como podríamos hacerlo hecho a donde pito se nos antojara) o ...
al redefinir el método nieto agregar un parámetro den entrada para implementar ciertas condiciones de funcionalidad. Con esto llamamos naturalmente al método padre (B), y el padre al método de su padre (A).

Sabemos que las dos soluciones no son las ideales, pero cual de las dos es la menos peor ?
__________________
| Cabeza De Raton |

Última edición por Calisco; 01/08/2008 a las 08:54
  #10 (permalink)  
Antiguo 01/08/2008, 08:44
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años
Puntos: 2135
Respuesta: LLamar a metodo abuelo.

Creo se habia discutido un tema similar hace poco (y con Symfony tambien) no se si sea que Symfony esta mal diseñado o no sea tan extensible...

Pero la solucion mas concreta y correcta, ya que haciendolo de la forma que lo planteas es dificil llamar al abuelo. La solucion fue, crear un metodo nuevo en A que llame al metodo que sobrecargas en B, y desde C llamas a ese metodo:
Código PHP:
class {
     public function 
elMetodo() {
              echo 
"soy el metodo especial de A";
     }

     public function 
aliasElMetodo() {
             
$this->elMetodo();
     }
}

class 
extends {
      public function 
elMetodo() {
               echo 
"Yo soy el metodo sobrecargado en B";
               
parent::elMetodo();
      }
}

class 
extends {
       public function 
elMetodo() {
               
"Yo soy el metodo sobrecargado en C, pero necesito hablarle a A";
               
$this->aliasElMetodo();
       }
}

$c = new C();
$c->elMetodo(); 
Saludos.
  #11 (permalink)  
Antiguo 01/08/2008, 08:56
Avatar de Calisco  
Fecha de Ingreso: marzo-2004
Ubicación: Neuquen
Mensajes: 732
Antigüedad: 20 años, 1 mes
Puntos: 4
Respuesta: LLamar a metodo abuelo.

Claro, pero estas editando la clase A agregando el método AliasElMetodo().
Ahora, cuando instanciamos un objeto con la clase C ...
al usar $MiObjeto->aliasElMetodo(); ... efectivamente usamos la declaración de miMetodo() de la clase A ?
__________________
| Cabeza De Raton |
  #12 (permalink)  
Antiguo 01/08/2008, 09:00
Avatar de enriqueplace  
Fecha de Ingreso: mayo-2005
Ubicación: Uruguay / Argentina
Mensajes: 1.102
Antigüedad: 19 años
Puntos: 32
Respuesta: LLamar a metodo abuelo.

¿Si todos los métodos son publicos, por qué no?

El problema se daría cuando tienes métodos privados.
__________________
Blog phpsenior.com Cursos a Distancia surforce.com
  #13 (permalink)  
Antiguo 01/08/2008, 09:03
Avatar de Calisco  
Fecha de Ingreso: marzo-2004
Ubicación: Neuquen
Mensajes: 732
Antigüedad: 20 años, 1 mes
Puntos: 4
Respuesta: LLamar a metodo abuelo.

Pero por mas que hayas redefinido el método miMetodo en las clase B ?
__________________
| Cabeza De Raton |
  #14 (permalink)  
Antiguo 01/08/2008, 09:11
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años
Puntos: 2135
Respuesta: LLamar a metodo abuelo.

Por eso cree el Alias, ejecuta el código y veras

Saludos.
  #15 (permalink)  
Antiguo 01/08/2008, 09:13
Avatar de Calisco  
Fecha de Ingreso: marzo-2004
Ubicación: Neuquen
Mensajes: 732
Antigüedad: 20 años, 1 mes
Puntos: 4
Respuesta: LLamar a metodo abuelo.

Bueno, estoy oxidado con PHP; mas de lo que hubiese pensado. Muy buena técnica esa.
Pero vuelvo al ruedo y pregunto una vez mas ...cual de las soluciones es la menos peor ?
__________________
| Cabeza De Raton |
  #16 (permalink)  
Antiguo 01/08/2008, 09:21
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años
Puntos: 2135
Respuesta: LLamar a metodo abuelo.

Mmmm cual es el la otra solución? Adicionalmente, esto no es solo de PHP, en cualquier lenguaje OO puedes hacerlo.

Saludos.
  #17 (permalink)  
Antiguo 01/08/2008, 09:46
Avatar de Calisco  
Fecha de Ingreso: marzo-2004
Ubicación: Neuquen
Mensajes: 732
Antigüedad: 20 años, 1 mes
Puntos: 4
Respuesta: LLamar a metodo abuelo.

Cita:
Iniciado por Calisco Ver Mensaje
Claro. Pero la realidad es que tenemos una parte del diseño implementada, y nos guste o no, no la podemos cambiar. Partamos de estas condiciones iniciales. Las fichas están en posición, y agarramos el tablero en el medio juego.
Frente a esta maldita condiciones, y analizando ya las particularidades de la aplicación, pudimos parchar un agujero de dos formas. Una es saltando por referencia al metodo abuelo (como podríamos hacerlo hecho a donde pito se nos antojara) o ...
al redefinir el método nieto agregar un parámetro den entrada para implementar ciertas condiciones de funcionalidad. Con esto llamamos naturalmente al método padre (B), y el padre al método de su padre (A).

Sabemos que las dos soluciones no son las ideales, pero cual de las dos es la menos peor ?
Lo que porpones GatorV no es una solución en este caso, porque no podemos tocar la clase A.
__________________
| Cabeza De Raton |
  #18 (permalink)  
Antiguo 01/08/2008, 10:12
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años
Puntos: 2135
Respuesta: LLamar a metodo abuelo.

Si no puedes tocar la clase A, entonces tendras que hacer lo de agregar un parametro directo en B, aunque con eso rompez con la metodologia de que los metodos deben de ser genericos y pasan a ser especificos.

Pero como dices si no hay otra posibilidad, pues no queda de otra, a veces hay que hacer cosas para brindar la funcionalidad, aunque casi siempre como dice enrique, es problema de diseño inicial y no a la implementacion.

Saludos.
  #19 (permalink)  
Antiguo 01/08/2008, 11:29
Avatar de Genetix  
Fecha de Ingreso: febrero-2002
Ubicación: Lima - Perú
Mensajes: 1.600
Antigüedad: 22 años, 2 meses
Puntos: 45
Respuesta: LLamar a metodo abuelo.

Lo ideal seria que se mejore el diseño para no tener problemas futuros.

Una solución que se me ocurrió seria esto, talvez no sea lo mejor, pero te puede ayudar.
Código PHP:
class {
     public function 
elMetodo() {
              echo 
"soy el metodo especial de A";
     }
}

class 
extends {
      public function 
elMetodo() {
               echo 
"Yo soy el metodo sobrecargado en B";
               
parent::elMetodo();
      }
}

class 
{
      
      private 
$_classA;
      private 
$_classB;
      
      public function 
__construct(A $classAB $classB ){
        
$this->_classA $classA;  
        
$this->_classB $classB;
      }
      
      public function 
getComponent($component){
        switch(
$component){
            case 
'A':
                return 
$this->_classA;
                break;
            case 
'B':
             return 
$this->_classB;
             break;
        }
     }
      
}

$c = new C(new A(), new B());
$c->getComponent('A')->elMedoto() //soy el metodo especial de A
$c->getComponent('B')->elMedoto() //Yo soy el metodo sobrecargado en B 
Investiga sobre Dependence Injection creo que ahí podría estar la solución a tu problema.

Saludos
__________________
"El conocimiento nos hace responsables."
twitter: @benjamingb
blog personal: http://codigolinea.com
ZF Manual en español http://manual.zfdes.com
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 09:56.