ACTUALIZACIÓN : PHP 7.4 ahora admite covarianza y contravarianza, lo que aborda el problema principal planteado en esta pregunta.
Me he encontrado con un problema con el uso de la sugerencia de tipo de retorno en PHP 7. Tengo entendido que la sugerencia : self
significa que tiene la intención de que una clase de implementación regrese a sí misma. Por lo tanto, usé : self
en mis interfaces para indicar eso, pero cuando intenté implementar la interfaz, obtuve errores de compatibilidad.
La siguiente es una demostración simple del problema con el que me he encontrado:
interface iFoo
{
public function bar (string $baz) : self;
}
class Foo implements iFoo
{
public function bar (string $baz) : self
{
echo $baz . PHP_EOL;
return $this;
}
}
(new Foo ()) -> bar ("Fred")
-> bar ("Wilma")
-> bar ("Barney")
-> bar ("Betty");
El resultado esperado fue:
Fred Wilma Barney Betty
Lo que realmente obtengo es:
Error fatal de PHP: Declaración de Foo :: bar (int $ baz): Foo debe ser compatible con iFoo :: bar (int $ baz): iFoo en test.php en la línea 7
La cosa es que Foo es una implementación de iFoo, por lo que puedo decir, la implementación debería ser perfectamente compatible con la interfaz dada. Presumiblemente podría solucionar este problema cambiando la interfaz o la clase de implementación (o ambas) para devolver la pista a la interfaz por nombre en lugar de usar self
, pero tengo entendido que semánticamente self
significa "devolver la instancia de la clase en la que acaba de llamar al método ". Por lo tanto, cambiarlo a la interfaz significaría en teoría que podría devolver cualquier instancia de algo que implemente la interfaz cuando mi intención es que la instancia invocada sea lo que se devolverá.
¿Es esto un descuido en PHP o es una decisión de diseño deliberada? Si es lo primero, ¿hay alguna posibilidad de que se solucione en PHP 7.1? Si no es así, ¿cuál es la forma correcta de devolver la sugerencia de que su interfaz espera que devuelva la instancia en la que acaba de llamar al método para encadenar?