una sirve resueltos que poo para interfaces ejercicios ejemplo clases clase abstractas abstracta php oop interface abstract-class

php - sirve - Interfaz o una clase abstracta: ¿cuál usar?



interfaces poo (11)

Explique cuándo debo usar una interface PHP y cuándo debo usar una abstract class .

¿Cómo puedo cambiar mi abstract class en una interface ?


¿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 tú 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 de Frutas 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 no pueden tener un cuerpo. En las 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


Además, solo me gustaría agregar aquí que solo porque cualquier otro lenguaje OO tenga algún tipo de interfaces y abstracción tampoco significa que tengan el mismo significado y propósito que en PHP. El uso de abstraction / 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, expandible 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 buscar sinónimos también.

Y esto podría ayudarte como metáfora:

INTERFAZ

Digamos que usted hornea un nuevo tipo de pastel con fresas e inventó una receta que describe los ingredientes y los pasos. Solo tú sabes por qué está sabiendo tan bien y les gusta a tus invitados. Entonces decides publicar tu receta para que otras personas también puedan probar ese pastel.

El punto aquí es

- para hacerlo bien
- ser cuidadoso
- para prevenir 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 dura qué hacer (como agitarse)
- para decir qué cosas PUEDES hacer pero NO TIENES que

Exactamente ESTO es lo que describe las interfaces. Es una guía, un conjunto de instrucciones que observan el contenido de la receta. Igual que si quisiera crear 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 no debes hacer. Reglas que lo sostienen: si desobedeces una, se romperá todo el constructo.


ABSTRACCIÓN

Para continuar con esta metáfora aquí ... imagina, eres el invitado esta vez que comes 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 se podría considerar una extensión de la torta original. Básicamente, haces una abstracción de ella creando una nueva receta porque es un poco diferente. Tiene unos pasos nuevos y otros ingredientes. Sin embargo, la versión de Black Berry tiene algunas partes que tomaste del original: estos son los pasos básicos que debe tener todo tipo de torta. 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? Así que tomas las bayas negras esta vez. Hecho.

Ahí lo tienes, has extendido el pastel, seguido la interfaz y abstraído de pasos e ingredientes.


Bueno, las diferencias técnicas entre una clase abstracta y una interfaz como ya se han enumerado en 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.

Tomemos un ejemplo. Un monitor de computadora es una entidad y debe ser representado como clase.

class Monitor{ private int monitorNo; }

Bueno, está diseñado para proporcionarle una interfaz de pantalla. Así que la funcionalidad debe ser definida por una interfaz.

interface Display{ void display(); }

Bueno, hay muchas otras cosas que considerar como se explica en otras respuestas, pero esta es la cosa más básica que la mayoría de las personas ignoran al escribir el código.


Desde un punto de vista filosófico:

  • Una clase abstracta representa una relación "es una". Digamos que tengo frutos, bueno, tendría una clase abstracta de frutas que comparte responsabilidades comunes y comportamiento común.

  • Una interfaz representa una relación "debería hacer". 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 puede 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 sea necesario, 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: La respuesta de Vivek Vermani aporta "es un" / "debería hacer", no quise robar su respuesta, ¡solo para reutilizar los términos porque me gustaron!


La mejor práctica es usar una interfaz para especificar el contrato y una clase abstracta como solo una implementación del mismo. Esa clase abstracta puede completar gran parte de la plantilla para que pueda crear una implementación simplemente anulando lo que necesita o desea sin forzarlo a usar una implementación en particular.


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.


Las diferencias entre una Abstract Class y una 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 de una clase abstracta debe 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 .

  • Las clases completamente diferentes y no relacionadas se pueden agrupar lógicamente usando una interfaz.


Para agregar a algunas de las respuestas ya excelentes:

  • Las clases abstractas le permiten proporcionar cierto grado de implementación, las interfaces son puras plantillas. 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 define o debe declararse abstracta.

  • Las interfaces pueden ayudar a administrar el hecho de que, como Java, PHP no admite la herencia múltiple. Una clase de PHP solo puede extender un solo padre. Sin embargo, puede hacer una promesa de clase de implementar tantas interfaces como desee.

  • type: 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 se unen efectivamente a tipos que de otra manera no están relacionados.

  • una clase puede extender una superclase e implementar cualquier número de interfaces:

    class SubClass extends ParentClass implements Interface1, Interface2 { // ... }

Explique cuándo debo usar una interfaz y cuándo debo usar la clase abstracta.

Use una interfaz cuando necesite proporcionar solo una plantilla sin ninguna implementación, y quiere asegurarse de que cualquier clase que implemente esa interfaz tenga los mismos métodos que cualquier otra clase que la implemente (al menos).

Utilice 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 en una interfaz?

Aquí hay un caso / ejemplo simplificado. Saque todos los detalles de la implementación. Por ejemplo, cambie su clase abstracta de:

abstract class ClassToBuildUpon { public function doSomething() { echo ''Did something.''; } }

a:

interface ClassToBuildUpon { public function doSomething(); }


Solo para incluir esto en la mezcla, pero como Cletus mencionó usar una interfaz junto con una clase abstracta, a menudo la uso 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 usan para implementar el patrón de decorador.

Además, es posible que no esté en la base aquí porque no soy 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 de manera programática. Mover los elementos contratables 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 psudo-có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)


Solo quería agregar un ejemplo de cuándo es posible que necesite 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.

  • Tengo varias clases abstractas que manejan la crudeza estándar y también algunas funcionalidades especializadas como conversión y transmisión para diferentes categorías de archivos.
  • La interfaz de acceso a archivos define un conjunto común de métodos que son necesarios para obtener, almacenar y eliminar un archivo.

De esta manera, puedo tener varias 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 con los métodos de acceso en lugar de lo que habría 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.


Use una interfaz cuando desee forzar a los desarrolladores que trabajan en su sistema (incluido usted mismo) a implementar un número determinado de métodos en las clases que construirán.

Use una clase abstracta cuando quiera forzar a los desarrolladores que trabajan en su sistema (incluido usted mismo) a implementar un número determinado de métodos y desea proporcionar algunos métodos básicos que los ayudarán a desarrollar sus clases secundarias.

Otra cosa a tener en cuenta es que las clases de clientes solo pueden extender una clase abstracta, mientras que pueden implementar múltiples interfaces. Por lo tanto, si está definiendo sus contratos de comportamiento en clases abstractas, eso significa que cada clase secundaria solo puede ajustarse a un solo contrato. A veces esto es bueno, cuando quiere forzar a sus programadores de usuarios a lo largo de un camino particular. Otras veces sería malo. Imagínese si las interfaces contables e iteradores 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.