Interfaz o clase abstracta: ¿cuál usar?
Por favor explique cuándo debo usar PHP interface
y cuándo debo usar unabstract class
?
¿ Cómo puedo cambiar mi abstract class
entrada a una interface
?
Utilice una interfaz cuando desee obligar a los desarrolladores que trabajan en su sistema (incluido usted mismo) a implementar una cantidad determinada de métodos en las clases que crearán.
Utilice una clase abstracta cuando desee obligar a los desarrolladores que trabajan en su sistema (incluido usted mismo) a implementar una cantidad determinada de métodos y desee proporcionar algunos métodos básicos que les ayudarán 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ás definiendo tus contratos de comportamiento en clases abstractas, eso significa que cada clase secundaria solo puede ajustarse a un único contrato. A veces esto es algo bueno cuando desea forzar a sus usuarios-programadores a seguir un camino particular. Otras veces sería malo. Imagínese si las interfaces Countable e Iterator de PHP fueran clases abstractas en lugar de interfaces.
Un enfoque que es común cuando no está seguro de qué camino tomar (como lo menciona 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 a partir de una clase abstracta debería estar relacionada lógicamente.
Interfaz
Una interfaz no puede contener ninguna funcionalidad . Solo contiene definiciones de los métodos.
La clase derivada DEBE proporcionar código para todos los métodos definidos en la interfaz .
Se pueden agrupar lógicamente clases completamente diferentes y no relacionadas mediante una interfaz.
¿Por qué utilizar clases abstractas? El siguiente es un ejemplo simple de https://www.php.net/manual/en/language.oop5.abstract.php#95404 del usuario mbajoras.
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 hacer eso. Esto se logra haciendo que la clase Fruit sea abstracta, así como el método eat 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 puedes 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 cuerpo. En clases abstractas, pueden hacerlo.
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
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 gran parte del texto estándar para que pueda crear una implementación simplemente anulando lo que necesita o desea sin obligarlo a usar una implementación en particular.