2009-12-27 12 views
6

He definido una clase abstracta y un método que se supone que devuelve el nombre de un archivo de plantilla. El usuario subclasifica esta clase abstracta e implementa ese método para devolver el nombre del archivo de la plantilla. Pero el problema es que no ocurre ninguna advertencia o lo que sea, si el usuario simplemente no devuelve nada.¿Puedo forzar un método de una clase abstracta para devolver algo?

¿Cómo podría asegurar esto? El código que llama a este método pertenece al marco, por lo que podría hacer algunas cosas de lujo con settype($returnVal, 'string') tal vez, si eso ayuda? ¿Hay mejores soluciones?

Respuesta

11

En PHP, no se puede "forzar" un método para devolver nada, y no es posible, incluso con clases/métodos abstractos, ni interfaces.

Lo mejor que puede hacer es indicar que la aplicación debe devolver algo, usando un comentario - pero no se puede obligar a la gente a hacerlo:

/** 
* @param string $a blah blah 
* @return int The return value blah blah 
*/ 
public function my_method($a); 

Por supuesto, si está llamando a este método (la puesta en práctica) de su marco, se puede comprobar lo que se ha vuelto, y una excepción si no corresponde a lo que se esperaba ...


y aquí es un ejemplo rápido de cómo esto podría ser implementado:

class ClassA { 
    /** 
    * @param string $a blah blah 
    * @return ClassB The return value blah blah 
    */ 
    public function my_method($a) { 
     echo 'blah'; 
    } 
} 

class ClassB { 
    // ... 
} 


$a = new ClassA(); 
$returned = $a->my_method(10); 
if (!$returned instanceof ClassB) { 
    throw new Exception("Should have returned an instance of ClassB !"); 
} 

Aquí, como el método no devuelve una instancia de ClassB, se lanzará la excepción.

+1

bien, pero sería posible verificar el valor de retorno, ¿no? – openfrog

+1

@openfrog: sí, por supuesto, pero tendrá que codificarlo usted mismo: PHP no lo impone (edité mi respuesta mientras publicaba su comentario; lo editaré de nuevo con un ejemplo) –

+0

Eso es genial . ¡¡Gracias!! Prácticamente respondió dos de mis preguntas a la vez :-) – openfrog

1

Por lo que yo sé, no hay forma de lograr indicaciones tipo para los valores de retorno en PHP. Desde PHP 5, hay indicaciones limitadas para function parameters.

Pero incluso si hubiera, lo que está tratando de hacer no es un trabajo para el tipo de alusión. ¿Qué sucede si la cadena que devuelvo está vacía? Tendrá que verificar el valor de retorno donde sea que se llame al método, y reaccionar de manera apropiada.

4

La única manera que puedo pensar para hacer esto es crear un método public final en la clase padre que utilizará el código de llamada, y un método protected que será llamado por el método public final. El método protected contiene la funcionalidad y el método public final valida el valor de retorno del método protected.

class A { 

    public final call_this($param) { 

     $return_value = $this->extend_this($param); 

     // validate $return_value 
     if($return_value == '') 
      throw new Exception("uh-oh! Don't return an empty string!"); 

     return $return_value; 

    } 

    protected extend_this($param) { 

     // default behavior 

     return $whatever; 

    } 

} 

class B extends A { 

    protected extend_this($param) { 

     // new behavior 

     return ''; //whoops! 

    } 

} 

$b = new B; 
$b->call_this("testing testing 123"); 
//exception! 

Esto puede ser un poco confuso para la persona extendiendo la clase sin embargo, si intenta algo como esto, asegúrese de que está bien documentado.

public final es un método público que no se puede anular, en caso de que no lo supiera. También tenga en cuenta que esto solo funcionará en PHP 5.0.0 o mejor.

+0

ya no es cierto desde php7.1 –

6

En PHP 7 es posible obligar a un método para devolver una instancia de una clase como esta:

class MyClass 
{ 
    public function getData(): MyData 
    { 
     return 1234; //TypeError! 
    } 
} 
class MyData 
{ 
} 

De esta manera, el siguiente código es válido y lanza un TypeError:

$obj = new MyClass(); 
$obj->getData(); 

Sandbox.

+2

Esto también se puede hacer en un método abstracto: función pública abstracta getData(): MyData; –

Cuestiones relacionadas