namespace ejemplos php oop interface traits

ejemplos - traits php



¿Por qué PHP Trait no puede implementar interfaces? (3)

Me pregunto por qué PHP Trait (PHP 5.4) no puede implementar interfaces.

Actualización de la respuesta de user1460043 => ... no puede requerir una clase que la use para implementar una interfaz específica

Entiendo que podría ser obvio, porque la gente podría pensar que si una Class A está utilizando un Trait T que está implementando una interface I , entonces la Class A debería implementar la interface I indirectamente (y esto no es cierto porque la Class A podría cambiar el nombre de los métodos de rasgo).

En mi caso, mi característica es llamar a los métodos desde la interfaz que implementa la clase que usa el rasgo.

El rasgo es, de hecho, una implementación de algunos métodos de la interfaz. Entonces, quiero "diseñar" en el código que cada clase que quiera usar mi característica tenga que implementar la interfaz. Eso le permitiría al Trait usar los métodos de clase definidos por la interfaz y asegurarse de que existan en la clase.


[...] para "diseñar" en el código que todas las clases que quieran usar mi rasgo tengan que implementar la interfaz. Eso le permitiría al Trait usar los métodos de clase definidos por la interfaz y asegurarse de que existan en la clase.

Esto suena muy razonable y no diría que tiene que haber algo mal con su diseño. Se han sugerido rasgos con esta idea en mente, vea el segundo punto aquí:

  • Un rasgo proporciona un conjunto de métodos que implementan el comportamiento.
  • Un rasgo requiere un conjunto de métodos que sirven como parámetros para el comportamiento proporcionado.
  • [...]

Schärli et al, Rasgos: Unidades compostables de comportamiento, ECOOP''2003, LNCS 2743, pp. 248-274, Springer Verlag, 2003, página 2

Por lo tanto, sería más apropiado decir que desea un rasgo para requerir una interfaz, no para "implementarla".

No veo una razón por la cual debería ser imposible tener esta característica de "rasgo requiere (sus clases de consumidor para implementar) una interfaz" en PHP, pero actualmente parece que falta.

Como señala @Danack en su answer , puede usar funciones abstractas en el rasgo para "requerirlas" de las clases que usan el rasgo. Desafortunadamente no puedes hacer esto con funciones privadas .


Hay un RFC: Rasgos con interfaces sugiere seguir para agregar al idioma:

trait SearchItem implements SearchItemInterface { ... }

Los métodos requeridos por la interfaz pueden ser implementados por el rasgo, o declarados como abstractos, en cuyo caso se espera que la clase que usa el rasgo lo implemente.

Actualmente, esta característica no es compatible con el idioma, pero está bajo consideración (el estado actual del RFC es: En discusión ).


La versión realmente corta es más simple porque no puedes. Así no es como funcionan los Rasgos.

Cuando escribes, use SomeTrait; en PHP le está diciendo (efectivamente) al compilador que copie y pegue el código del Rasgo en la clase donde se está utilizando.

Porque el use SomeTrait; está dentro de la clase, no puede agregar implements SomeInterface a la clase, porque eso tiene que estar fuera de la clase.

"¿Por qué no hay tipos de Rasgos en PHP?"

Porque no pueden ser instanciados. Los rasgos son en realidad solo una construcción de lenguaje (que le dice al compilador que copie y pegue el código de rasgo en esta clase) en oposición a un objeto o tipo al que el código puede hacer referencia.

Entonces, quiero "diseñar" en el código que cada clase que quiera usar mi característica tenga que implementar la interfaz.

Esto se puede aplicar utilizando una clase abstracta para use el rasgo y luego extender las clases desde él.

interface SomeInterface{ public function someInterfaceFunction(); } trait SomeTrait { function sayHello(){ echo "Hello my secret is ".static::$secret; } } abstract class AbstractClass implements SomeInterface{ use SomeTrait; } class TestClass extends AbstractClass { static public $secret = 12345; //function someInterfaceFunction(){ //Trying to instantiate this class without this function uncommented will throw an error //Fatal error: Class TestClass contains 1 abstract method and must therefore be //declared abstract or implement the remaining methods (SomeInterface::doSomething) //} } $test = new TestClass(); $test->sayHello();

Sin embargo, si necesitas hacer cumplir que cualquier clase que use un Rasgo tiene un método particular, creo que puedes estar usando rasgos donde deberías haber sido clases abstractas en primer lugar.

O que tienes tu lógica al revés. Se supone que se requieren clases que implementen interfaces que tengan ciertas funciones, no es que si tienen ciertas funciones deben declararse a sí mismas implementando una interfaz.

Editar

En realidad, puede definir funciones abstractas dentro de los Rasgos para forzar a una clase a implementar el método. p.ej

trait LoggerTrait { public function debug($message, array $context = array()) { $this->log(''debug'', $message, $context); } abstract public function log($level, $message, array $context = array()); }

Sin embargo, esto todavía no le permite implementar la interfaz en el rasgo, y aún huele como un mal diseño, ya que las interfaces son mucho mejores que los rasgos para definir un contrato que una clase debe cumplir.