Por favor explique cuándo debo usar un PHP interface
y cuándo debo usar un abstract class
?
¿Cómo puedo cambiar mi entrada abstract class
a una interface
?
Por favor explique cuándo debo usar un PHP interface
y cuándo debo usar un abstract class
?
¿Cómo puedo cambiar mi entrada abstract class
a una interface
?
Respuestas:
Use una interfaz cuando quiera forzar a los desarrolladores que trabajan en su sistema (incluido usted mismo) para implementar un número determinado de métodos en las clases que van a construir.
Utilice una clase abstracta cuando desee forzar a los desarrolladores que trabajan en su sistema (incluido usted mismo) para implementar un número determinado de métodos y desee proporcionar algunos métodos básicos que los ayuden a desarrollar sus clases secundarias.
Otra cosa a tener en cuenta es que las clases de cliente solo pueden extender una clase abstracta, mientras que pueden implementar múltiples interfaces. Entonces, si está definiendo sus contratos de comportamiento en clases abstractas, eso significa que cada clase secundaria solo puede conformarse a un solo contrato. A veces esto es bueno, cuando quieres forzar a tus programadores de usuarios a seguir un camino en particular. Otras veces sería malo. Imagínese si las interfaces Contable e Iterador de PHP fueran clases abstractas en lugar de interfaces.
Un enfoque que es común cuando no está seguro de qué camino tomar (como se menciona en cletus a continuación ) es crear una interfaz y luego hacer que su clase abstracta implemente esa interfaz.
Las diferencias entre an Abstract Class
y an Interface
:
Clases abstractas
Una clase abstracta puede proporcionar alguna funcionalidad y dejar el resto para la clase derivada .
La clase derivada puede o no anular las funciones concretas definidas en la clase base.
Una clase secundaria extendida desde una clase abstracta debería estar relacionada lógicamente.
Interfaz
Una interfaz no puede contener ninguna funcionalidad . Es solamente contiene las definiciones de los métodos.
La clase derivada DEBE proporcionar código para todos los métodos definidos en la interfaz .
Las clases completamente diferentes y no relacionadas pueden agruparse lógicamente mediante una interfaz.
abstract class X implements Y
y class X implements Y
?
abstract class X implements Y
declara que la funcionalidad masiva de X debe implementarse en una clase derivada y que tanto la clase abstracta como la derivada deben contener funciones definidas en Y, mientras que class X implements Y
solo implica que la clase X debe contener funciones definidas en Y. Si su interfaz Y no está destinado a ser implementado por ninguna otra clase que XI realmente omitiría la definición de Y como interfaz y solo implementaría las funciones en Y como función abstracta pública / protegida / privada para asegurarse de que se implementen en la clase derivada.
¿Por qué usar clases abstractas? El siguiente es un ejemplo simple. Digamos que tenemos el siguiente código:
<?php
class Fruit {
private $color;
public function eat() {
// chew
}
public function setColor($c) {
$this->color = $c;
}
}
class Apple extends Fruit {
public function eat() {
// chew until core
}
}
class Orange extends Fruit {
public function eat() {
// peeling
// chew
}
}
Ahora te doy una manzana y te la comes. A qué sabe esto? Sabe a manzana.
<?php
$apple = new Apple();
$apple->eat();
// Now I give you a fruit.
$fruit = new Fruit();
$fruit->eat();
¿A qué sabe eso? Bueno, no tiene mucho sentido, así que no deberías poder hacerlo. Esto se logra haciendo que la clase Fruit sea abstracta, así como el método de comer dentro de ella.
<?php
abstract class Fruit {
private $color;
abstract public function eat(){}
public function setColor($c) {
$this->color = $c;
}
}
?>
Una clase abstracta es como una interfaz, pero puede definir métodos en una clase abstracta mientras que en una interfaz todos son abstractos. Las clases abstractas pueden tener métodos vacíos y de trabajo / concretos. En las interfaces, las funciones definidas allí no pueden tener un cuerpo. En clases abstractas, pueden.
Un ejemplo del mundo real:
<?php
abstract class person {
public $LastName;
public $FirstName;
public $BirthDate;
abstract protected function write_info();
}
final class employee extends person{
public $EmployeeNumber;
public $DateHired;
public function write_info(){
//sql codes here
echo "Writing ". $this->LastName . "'s info to emloyee dbase table <br>";
}
}
final class student extends person{
public $StudentNumber;
public $CourseName;
public function write_info(){
//sql codes here
echo "Writing ". $this->LastName . "'s info to student dbase table <br>";
}
}
///----------
$personA = new employee;
$personB = new student;
$personA->FirstName="Joe";
$personA->LastName="Sbody";
$personB->FirstName="Ben";
$personB->LastName="Dover";
$personA->write_info();
// Writing Sbody's info to emloyee dbase table
$personB->write_info();
// Writing Dover's info to student dbase table
What does that taste like? Well, it doesn't make much sense, so you shouldn't be able to do that.
Ahora sé abstracto!
final
palabra clave? Gran post, gracias.
La mejor práctica es utilizar una interfaz para especificar el contrato y una clase abstracta como solo una implementación del mismo. Esa clase abstracta puede completar una gran cantidad de repeticiones para que pueda crear una implementación simplemente anulando lo que necesita o desea sin obligarlo a usar una implementación particular.
Solo para incluir esto en la mezcla, pero como Cletus mencionó usar una interfaz junto con una clase abstracta, a menudo uso la interfaz para aclarar mi pensamiento de diseño.
Por ejemplo:
<?php
class parser implements parserDecoratorPattern {
//...
}
De esa manera, cualquiera que lea mi código (y quién sabe qué es un Patrón de decorador) sabrá de inmediato a) cómo construyo mi analizador yb) podrá ver qué métodos se utilizan para implementar el patrón de decorador.
Además, y puedo estar fuera de la base aquí no siendo un programador de Java / C ++ / etc., pero los tipos de datos pueden entrar en juego aquí. Sus objetos son de un tipo, y cuando los pasa, el tipo importa mediante programación. Mover sus elementos contraíbles a la interfaz solo dicta los tipos que devuelven los métodos, pero no el tipo base de la clase que lo implementa.
Es tarde y no puedo pensar en un mejor ejemplo de psudocódigo, pero aquí va:
<?php
interface TelevisionControls {};
class Remote implements TelevisionControls {};
class Spouse implements TelevisionControls {};
Spouse spouse = new Spouse();
Remote remote = new Remote();
isSameType = (bool)(remote == spouse)
La principal diferencia es que una clase abstracta puede contener una implementación predeterminada, mientras que una interfaz no puede.
Una interfaz es un contrato de comportamiento sin ninguna implementación.
Además, me gustaría agregar aquí que el hecho de que cualquier otro lenguaje OO tenga algún tipo de interfaz y abstracción también no significa que tengan el mismo significado y propósito que en PHP. El uso de abstracción / interfaces es ligeramente diferente, mientras que las interfaces en PHP en realidad no tienen una función real. Simplemente se utilizan por razones semánticas y relacionadas con el esquema. El punto es tener un proyecto lo más flexible posible, ampliable y seguro para futuras extensiones, independientemente de si el desarrollador tiene un plan de uso totalmente diferente o no.
Si su inglés no es nativo, puede buscar lo que realmente son abstracción e interfaces. Y busque sinónimos también.
Y esto podría ayudarte como metáfora:
INTERFAZ
Digamos que horneas un nuevo tipo de pastel con fresas y preparas una receta que describe los ingredientes y los pasos. Solo usted sabe por qué sabe tan bien y a sus invitados les gusta. Luego decides publicar tu receta para que otras personas puedan probar ese pastel también.
El punto aquí es
- para hacer las cosas bien
- para tener cuidado
- para evitar cosas que podrían salir mal (como demasiadas fresas o algo así)
- para que sea fácil para las personas que lo prueban
- para decirle cuánto tiempo es qué hacer (como agitar )
- para decir qué cosas PUEDE hacer pero NO DEBE
Exactamente ESTO es lo que describe las interfaces. Es una guía, un conjunto de instrucciones que observan el contenido de la receta. Lo mismo que crearía un proyecto en PHP y desea proporcionar el código en GitHub o con sus compañeros o lo que sea. Una interfaz es lo que la gente puede hacer y lo que usted no debería hacer. Reglas que lo sostienen: si desobedeces una, la construcción completa se romperá.
ABSTRACCIÓN
Para continuar con esta metáfora aquí ... imagínese, usted es el invitado esta vez comiendo ese pastel. Entonces estás probando ese pastel usando la receta ahora. Pero desea agregar nuevos ingredientes o cambiar / omitir los pasos descritos en la receta. Entonces, ¿qué viene después? Planea una versión diferente de ese pastel. Esta vez con bayas negras y no bayas de paja y más crema de vainilla ... delicioso.
Esto es lo que podría considerar una extensión del pastel original. Básicamente haces una abstracción al crear una nueva receta porque es muy diferente. Tiene algunos pasos nuevos y otros ingredientes. Sin embargo, la versión de baya negra tiene algunas partes que tomó del original: estos son los pasos básicos que debe tener todo tipo de pastel. Como ingredientes como la leche: eso es lo que tiene cada clase derivada.
Ahora desea intercambiar ingredientes y pasos, y estos DEBEN definirse en la nueva versión de ese pastel. Estos son métodos abstractos que deben definirse para el nuevo pastel, porque debería haber una fruta en el pastel, pero ¿cuál? Entonces tomas las bayas negras esta vez. Hecho.
Ahí tienes, has extendido el pastel, seguido la interfaz y los pasos e ingredientes abstraídos de él.
Para agregar a algunas de las respuestas ya excelentes:
Las clases abstractas le permiten proporcionar cierto grado de implementación, las interfaces son plantillas puras. Una interfaz solo puede definir la funcionalidad , nunca puede implementarla.
Cualquier clase que implemente la interfaz se compromete a implementar todos los métodos que defina o debe declararse abstracta.
Las interfaces pueden ayudar a gestionar el hecho de que, como Java, PHP no admite la herencia múltiple. Una clase PHP solo puede extender a un solo padre. Sin embargo, puede hacer una promesa de clase para implementar tantas interfaces como desee.
tipo: para cada interfaz que implementa, la clase toma el tipo correspondiente. Debido a que cualquier clase puede implementar una interfaz (o más interfaces), las interfaces efectivamente unen tipos que de otro modo no están relacionados.
una clase puede extender una superclase e implementar cualquier cantidad de interfaces:
class SubClass extends ParentClass implements Interface1, Interface2 {
// ...
}
¿Explica cuándo debo usar una interfaz y cuándo debo usar la clase abstracta?
Use una interfaz cuando necesite proporcionar solo una plantilla sin implementación alguna y quiera asegurarse de que cualquier clase que implemente esa interfaz tenga los mismos métodos que cualquier otra clase que la implemente (al menos).
Use una clase abstracta cuando desee crear una base para otros objetos (una clase parcialmente construida). La clase que extiende su clase abstracta usará algunas propiedades o métodos definidos / implementados:
<?php
// interface
class X implements Y { } // this is saying that "X" agrees to speak language "Y" with your code.
// abstract class
class X extends Y { } // this is saying that "X" is going to complete the partial class "Y".
?>
¿Cómo puedo cambiar mi clase abstracta a una interfaz?
Aquí hay un caso / ejemplo simplificado. Saque todos los detalles de implementación. Por ejemplo, cambie su clase abstracta de:
abstract class ClassToBuildUpon {
public function doSomething() {
echo 'Did something.';
}
}
a:
interface ClassToBuildUpon {
public function doSomething();
}
Desde un punto de vista filosófico:
Una clase abstracta representa una relación "es una". Digamos que tengo frutas, bueno, tendría una clase de resumen de frutas que comparte responsabilidades y comportamientos comunes.
Una interfaz representa una relación "debería hacerlo". Una interfaz, en mi opinión (que es la opinión de un desarrollador junior), debe ser nombrada por una acción, o algo parecido a una acción, (Lo siento, no puedo encontrar la palabra, no soy un hablante nativo de inglés) Digamos IEatable. Sabes que se puede comer, pero no sabes lo que comes.
Desde un punto de vista de codificación:
Si sus objetos tienen código duplicado, es una indicación de que tienen un comportamiento común, lo que significa que podría necesitar una clase abstracta para reutilizar el código, lo que no puede hacer con una interfaz.
Otra diferencia es que un objeto puede implementar tantas interfaces como necesite, pero solo puede tener una clase abstracta debido al "problema del diamante" (¡consulte aquí para saber por qué! Http://en.wikipedia.org/wiki/ Multiple_inheritance # The_diamond_problem )
Probablemente olvide algunos puntos, pero espero que pueda aclarar las cosas.
PD: El "es un" / "debería hacer" viene de la respuesta de Vivek Vermani, ¡no quise robar su respuesta, solo para reutilizar los términos porque me gustaron!
Las diferencias técnicas entre una clase abstracta y una interfaz ya se enumeran en las otras respuestas con precisión. Quiero agregar una explicación para elegir entre una clase y una interfaz mientras escribo el código por el bien de la programación orientada a objetos.
Una clase debe representar una entidad, mientras que una interfaz debe representar el comportamiento.
Pongamos un ejemplo. Un monitor de computadora es una entidad y debe representarse como una clase.
class Monitor{
private int monitorNo;
}
Está diseñado para proporcionarle una interfaz de pantalla, por lo que la funcionalidad debe estar definida por una interfaz.
interface Display{
void display();
}
Hay muchas otras cosas a considerar como se explica en las otras respuestas, pero esta es la cosa más básica que la mayoría de la gente ignora al codificar.
PHP
Solo quería agregar un ejemplo de cuándo puede necesitar usar ambos. Actualmente estoy escribiendo un controlador de archivos vinculado a un modelo de base de datos en una solución ERP de propósito general.
De esta manera, tengo múltiples plantillas para diferentes archivos y un conjunto común de métodos de interfaz con una clara distinción. La interfaz proporciona la analogía correcta a los métodos de acceso en lugar de lo que hubiera sido con una clase abstracta base.
Más adelante, cuando haga adaptadores para diferentes servicios de almacenamiento de archivos, esta implementación permitirá que la interfaz se use en otros lugares en contextos totalmente diferentes.
abstract
y lasinterface
clases, tu publicación lo dejó todo claro. Muchas gracias Alan