¿Puede una clase extender una clase e implementar una interfaz?

100

¿Puede una clase extender tanto una interfaz como otra clase en PHP?
Básicamente quiero hacer esto:

interface databaseInterface{
 public function query($q);
 public function escape($s);
 //more methods
}

class database{ //extends both mysqli and implements databaseInterface
 //etc.
}

¿Cómo haría uno esto, simplemente haciendo:

class database implements databaseInterface extends mysqli{ 

resulta en un error fatal:

Error de análisis: error de sintaxis, T_EXTENDS inesperado, esperando '{' en * archivo * en línea * línea *
Pim Jager
fuente
18
¡¿Cómo es esto tan localizado ?! "Es poco probable que esta pregunta ayude a futuros visitantes". Sin embargo, la mejor respuesta tiene 33 votos a favor y la pregunta 4 estrellas.
dualidad_

Respuestas:

177

Pruébelo al revés:

class database extends mysqli implements databaseInterface { ...}

Esto debería funcionar.

Simon Lehmann
fuente
Ahh, muchas gracias. ¿Por qué exactamente deberían ser al revés?
Pim Jager
14
Dado que solo puede heredar una clase y puede implementar cualquier número de interfaces, probablemente fue una cuestión de sintaxis. Además, recuerde, si su subclase implementa alguna interfaz, eso también aparecería en la lista de métodos implementados. Así que ponerlos en ese orden tiene cierto sentido.
Drew
¿Es una mala práctica?
Mohammed Shamshid
21

Sí puede. Solo necesita mantener el orden correcto.

class database extends mysqli implements databaseInterface { ... }

Además, una clase puede implementar más de una interfaz. Solo sepárelos con comas.

Sin embargo, me siento obligado a advertirle que extender la clase mysqli es una idea increíblemente mala . La herencia per se es probablemente el concepto más sobrevalorado y mal utilizado en la programación orientada a objetos.

En su lugar, recomendaría hacer cosas relacionadas con la base de datos de la manera mysqli (o la manera PDO).

Además, una cosa menor, pero las convenciones de nomenclatura sí importan. Su clase databaseparece más general entonces mysqli, por lo tanto sugiere que este último hereda databasey no al revés.

Michał Rudnicki
fuente
1
¿Por qué es una mala idea extender la clase mysqli?
Pim Jager
11
Primero, porque no es tuyo. Cuando los chicos de mysqli deciden cambiar algo, el comportamiento de la subclase también cambiará. En segundo lugar, la herencia se usa para ESPECIALIZAR, no EXTENDER con funcionalidad adicional. Esta es la cosa más incomprendida en OOP. Como regla general, tiendo a extender solo las clases abstractas.
Michał Rudnicki
Michal: ¿cómo sería diferente un cambio a mysqli para un desarrollador que usa un enfoque polimórfico frente a uno agregado / compuesto? Aún tendría que actualizar su código para manejar los cambios.
Peter Bailey
2
Estoy familiarizado con el patrón del adaptador. Solo digo que si el nombre de un método cambia o está obsoleto, aún necesitará cambiar el código en ambos escenarios. Si bien estoy de acuerdo en que un enfoque no polimórfico es mejor en este escenario, no creo que un adaptador sea "inmune" al cambio.
Peter Bailey
2
Solo tendrá que cambiar el código del adaptador, no todos los lugares que usan ese código. Con la composición, puede proporcionar una capa de compatibilidad sin importar qué, mientras que con la herencia puede llamarla, en el mejor de los casos, un truco. Y, me corrijo, el adaptador proporcionaría una mejor inmunidad al cambio.
Michał Rudnicki
6

sí, de hecho, si desea implementar múltiples interfaces, puede hacerlo así:

public class MyClass extends BaseClass implements myInterface1, myInterface2, myInterface3{ 

}
puntero nulo
fuente