2012-01-14 24 views
5

El siguiente ejemplo no funciona porque cuando se llama a parent en la clase A, php busca la clase padre de la clase A pero no existe. Prefiero que esta línea llame al Test() en la clase B.Llamando al método padre de la clase heredada de la clase base

¿Esto es posible?

(sé que esto parece como un ejemplo tonto, pero tiene una aplicación práctica)

abstract class A { 
    function CallParentTest() 
    { 
     return call_parent_method('Test'); 
    } 
} 

abstract class B extends A { 
    function Test() 
    { 
     return 'test passed'; 
    } 
} 

class C extends B { 
    function Test() 
    { 
     return $this->CallParentTest(); 
    } 
} 

$object = new C(); 
echo $object->Test(); 

Gracias!

EDITAR
me cambió la palabra clave parent a la formada por el método call_parent_method porque creo que puede haber sido confusa personas. Sé que no hay forma de hacer esto usando la palabra clave.

Tal como lo señaló David Harkness, estoy tratando de implementar el patrón de Método de plantilla, pero en lugar de usar dos nombres de métodos diferentes, estoy usando uno. B::Test() será el método predeterminado a menos que se sustituya por una funcionalidad alternativa.

+1

¿Existe una necesidad real de volver a declarar la función de prueba en la clase C? Porque si no redeclara Test en C, hará exactamente lo que usted solicite; llame al Test desde la clase B. –

+0

Sí, debe estar configurado de esta manera. Como dije, parece estúpido, pero esta es la versión simplista. – Godwin

+0

Podrías lograrlo haciendo algunos backflips serios en cada clase secundaria que anule el método principal al tomar la pila para determinar si 'A' es quien llama o no. Si es así, haz lo tuyo. Si no, llame al método principal. Sin embargo, esto será mucho más complicado que solo tener dos métodos, y recomiendo no hacerlo. –

Respuesta

6

Puede usar la reflexión para eludir el orden natural de las llamadas para los métodos anulados. En cualquier contexto simplemente cree un ReflectionMethod para el método que desea llamar e invocarlo. No necesita hacer esto desde la clase en sí, pero deberá llamar al setAccessible(true) si el método no es público.

class A { 
    public function bypassOverride() { 
     echo "Hi from A\n"; 
     $r = new ReflectionMethod('B', 'override'); 
     $r->invoke($this); 
    } 
} 

class B extends A { 
    public function override() { 
     echo "Hi from B\n"; 
    } 
} 

class C extends B { 
    public function override() { 
     echo "Hi from C\n"; 
     $this->bypassOverride(); 
    } 
} 

$c = new C; 
$c->override(); 

La salida de este es

Hi from C 
Hi from A 
Hi from B 

Se podría hacer bypassOverride() más genérico y moverlo a una clase de ayuda si usted tiene que hacer esto mucho.

+0

Gracias, veo lo que estás diciendo ahora y es un enfoque interesante, pero esto vuelve a poner la llamada al método principal en la clase C y dará como resultado una cantidad considerable de código duplicado. – Godwin

+0

Encontré una solución más fácil usando la reflexión. –

+0

Exactamente lo que estaba buscando. ¡Gracias! – Godwin

1

¿Esto es posible?

No tiene sentido utilizar la palabra clave parent excepto en las clases hijas. Su único propósito es ser utilizado por clases secundarios para llamar a los métodos que se anulan. Piense en llamadas principales multinivel donde un niño llama al método de su padre del mismo nombre y, a su vez, ese padre llama al es el método del padre del mismo nombre.

+0

Gracias, soy muy consciente de cómo funciona normalmente la herencia, lo que estoy tratando de hacer está ligeramente fuera de la norma. PHP tiene muchas formas dinámicas de llamar a los métodos y tal, me preguntaba si hay una manera de lograr esto. – Godwin

1

webbiedave es correcto con respecto a parent, pero parece que está intentando implementar el patrón Template Method donde la clase base abstracta llama a un método que se espera que implementen las subclases. Aquí hay un ejemplo que demuestra una manera horrible de manejar los errores en sus aplicaciones.

abstract class ExceptionIgnorer { 
    public function doIt() { 
     try { 
      $this->actuallyDoIt(); 
     } 
     catch (Exception $e) { 
      // ignore the problem and it might go away... 
     } 
    } 

    public abstract function actuallyDoit(); 
} 

class ErrorThrower extends ExceptionIgnorer { 
    public function actuallyDoIt() { 
     throw new RuntimeException("This will be ignored"); 
    } 
} 

$thrower = new ErrorThrower; 
$thrower->doIt(); // no problem 

Aquí doIt() es el método de la plantilla, ya que define el algoritmo general a seguir.

+0

Sí, lo estoy, estaba intentando ver si había una forma de lograr esto en PHP sin tener que tener dos nombres de método diferentes. Estoy planeando implementar el patrón de método de plantilla en muchos lugares a través de una aplicación grande, por lo que usar el mismo nombre facilitaría el desarrollo. – Godwin

Cuestiones relacionadas