oop - poo - para que sirve una clase abstracta




¿Cuál es la diferencia entre una interfaz y una clase abstracta? (20)

Interfaces

Una interfaz es un contrato : la persona que escribe la interfaz dice: " hey, acepto las cosas de esa manera ", y la persona que usa la interfaz dice " OK, la clase que escribo se ve así ".

Una interfaz es una cáscara vacía . Solo existen las firmas de los métodos, lo que implica que los métodos no tienen un cuerpo. La interfaz no puede hacer nada. Es sólo un patrón.

Por ejemplo (pseudo código):

// I say all motor vehicles should look like this:
interface MotorVehicle
{
    void run();

    int getFuel();
}

// My team mate complies and writes vehicle looking that way
class Car implements MotorVehicle
{

    int fuel;

    void run()
    {
        print("Wrroooooooom");
    }


    int getFuel()
    {
        return this.fuel;
    }
}

Implementar una interfaz consume muy poca CPU, porque no es una clase, solo un montón de nombres y, por lo tanto, no es necesario hacer una búsqueda costosa. Es genial cuando importa, como en dispositivos integrados.

Clases abstractas

Las clases abstractas, a diferencia de las interfaces, son clases. Son más caros de usar, porque hay una búsqueda que hacer cuando se hereda de ellos.

Las clases abstractas se parecen mucho a las interfaces, pero tienen algo más: puede definir un comportamiento para ellas. Se trata más de una persona que dice: "estas clases deberían verse así, y tienen eso en común, ¡así que llene los espacios en blanco!".

Por ejemplo:

// I say all motor vehicles should look like this:
abstract class MotorVehicle
{

    int fuel;

    // They ALL have fuel, so lets implement this for everybody.
    int getFuel()
    {
         return this.fuel;
    }

    // That can be very different, force them to provide their
    // own implementation.
    abstract void run();
}

// My teammate complies and writes vehicle looking that way
class Car extends MotorVehicle
{
    void run()
    {
        print("Wrroooooooom");
    }
}

Implementación

Si bien se supone que las clases e interfaces abstractas son conceptos diferentes, las implementaciones hacen que esa afirmación a veces sea falsa. A veces, ni siquiera son lo que crees que son.

En Java, esta regla se aplica con fuerza, mientras que en PHP, las interfaces son clases abstractas sin método declarado.

En Python, las clases abstractas son más un truco de programación que puede obtener del módulo ABC y en realidad está usando metaclases y, por lo tanto, clases. Y las interfaces están más relacionadas con la escritura duck en este lenguaje y es una mezcla de convenciones y métodos especiales que llaman descriptores (los métodos __method__).

Como es habitual en la programación, hay teoría, práctica y práctica en otro idioma :-)

¿Cuál es exactamente la diferencia entre una interfaz y una clase abstracta?


Algunas diferencias importantes:

En forma de tabla:

Según lo declarado por Joe de javapapers :

1. La principal diferencia es que los métodos de una interfaz Java son implícitamente abstractos y no pueden tener implementaciones. Una clase abstracta de Java puede tener métodos de instancia que implementa un comportamiento predeterminado.

2. Las variables declaradas en una interfaz Java son, por defecto, finales. Una clase abstracta puede contener variables no finales.

3. Los miembros de una interfaz Java son públicos por defecto. Una clase abstracta de Java puede tener los sabores habituales de los miembros de la clase como privado, protegido, etc.

4. La interfaz de Java debe implementarse utilizando palabras clave "implementos"; Una clase abstracta de Java debe extenderse usando la palabra clave "extiende".

5. Una interfaz puede extender otra interfaz de Java solamente, una clase abstracta puede extender otra clase de Java e implementar múltiples interfaces de Java.

6. Una clase Java puede implementar múltiples interfaces pero puede extender solo una clase abstracta.

7.Interfaz es absolutamente abstracto y no puede ser instanciado; Una clase abstracta de Java tampoco se puede crear una instancia, pero se puede invocar si existe un main ().

8. En comparación con las clases abstractas de java, las interfaces de java son lentas, ya que requiere un direccionamiento adicional.


El punto principal es que:

  • El resumen está orientado a objetos . Ofrece los datos básicos que un 'objeto' debería tener y / o funciones que debería poder realizar. Se ocupa de las características básicas del objeto: lo que tiene y lo que puede hacer. Por lo tanto, los objetos que heredan de la misma clase abstracta comparten las características básicas (generalización).
  • La interfaz está orientada a la funcionalidad . Define funcionalidades que un objeto debe tener. Independientemente del objeto que sea, siempre que pueda realizar estas funciones, que están definidas en la interfaz, está bien. Ignora todo lo demás. Un objeto / clase puede contener varias (grupos de) funcionalidades; por lo tanto, es posible que una clase implemente múltiples interfaces.

En resumen las diferencias son las siguientes:

Diferencias sintácticas entre la interfaz y la clase abstracta :

  1. Los métodos y los miembros de una clase abstracta pueden tener cualquier visibilidad. Todos los métodos de una interfaz deben ser públicos . // Ya no es verdad desde Java 9
  2. Una clase secundaria concreta de una clase abstracta debe definir todos los métodos abstractos. Una clase infantil abstracta puede tener métodos abstractos. Una interfaz que extiende otra interfaz no necesita proporcionar una implementación predeterminada para los métodos heredados de la interfaz principal.
  3. Una clase infantil solo puede ampliar una clase. Una interfaz puede extender múltiples interfaces. Una clase puede implementar múltiples interfaces.
  4. Una clase secundaria puede definir métodos abstractos con la misma o menos visibilidad restrictiva, mientras que la clase que implementa una interfaz debe definir todos los métodos de interfaz como públicos.
  5. Las clases abstractas pueden tener constructores pero no interfaces .
  6. Las interfaces de Java 9 tienen métodos privados estáticos.

En Interfaces ahora:

public static - apoyada
public abstract - apoyado
public default - soportado
private static - soportada
private abstract - error de compilación
private default - error de compilación
private - apoyado


Estoy construyendo un edificio de 300 pisos.

La interfaz del plano del edificio.

  • Por ejemplo, Servlet (I)

Edificio construido hasta 200 pisos - parcialmente completado --- abstracto

  • Implementación parcial, por ejemplo, servlet genérico y HTTP.

Construccion de edificios terminada- concreto

  • Implementación completa, por ejemplo, propio servlet.

Interfaz

  • No sabemos nada de implementación, solo requerimientos. Podemos ir por una interfaz.
  • Cada método es público y abstracto por defecto.
  • Es una clase abstracta 100% pura.
  • Si declaramos público no podemos declarar privado y protegido.
  • Si declaramos abstracto no podemos declarar final, estático, sincronizado, strictfp y nativo
  • Cada interfaz tiene pública, estática y final.
  • La serialización y el transitorio no son aplicables, porque no podemos crear una instancia en la interfaz
  • No volátil porque es definitivo.
  • Cada variable es estática
  • Cuando declaramos una variable dentro de una interfaz, necesitamos inicializar las variables mientras declaramos
  • Instancia y bloqueo estático no permitidos

Resumen

  • Implementación parcial
  • Tiene un método abstracto. Una adición, utiliza hormigón.
  • Sin restricción para modificadores de métodos de clase abstracta
  • Sin restricción para modificadores de variable de clase abstracta
  • No podemos declarar otros modificadores excepto el resumen.
  • No hay restricción para inicializar variables.

Tomado del sitio web de DurgaJobs


Interfaz: girar (girar a la izquierda, girar a la derecha).

Clase abstracta: Rueda.

Clase: volante, deriva de la rueda, expone el giro de interfaz

Una es para categorizar el comportamiento que puede ofrecerse en una amplia gama de cosas, la otra es para modelar una ontología de las cosas.


La comparación de la interfaz con la clase abstracta es incorrecta. Debería haber otras dos comparaciones: 1) interfaz vs. clase y 2) clase abstracta vs. final .

Interfaz vs clase

La interfaz es un contrato entre dos objetos. Por ejemplo, soy un cartero y usted es un paquete para entregar. Espero que sepas tu dirección de entrega. Cuando alguien me da un paquete, tiene que saber su dirección de entrega:

interface Package {
  String address();
}

La clase es un grupo de objetos que obedecen el contrato. Por ejemplo, soy una caja del grupo "Box" y obedezco el contrato requerido por el cartero. Al mismo tiempo obedezco otros contratos:

class Box implements Package, Property {
  @Override
  String address() {
    return "5th Street, New York, NY";
  }
  @Override
  Human owner() {
    // this method is part of another contract
  }
}

Resumen vs Final

La clase abstracta es un grupo de objetos incompletos. No se pueden usar, porque faltan algunas partes. Por ejemplo, soy una casilla abstracta para GPS: sé cómo verificar mi posición en el mapa:

abstract class GpsBox implements Package {
  @Override
  public abstract String address();
  protected Coordinates whereAmI() {
    // connect to GPS and return my current position
  }
}

Esta clase, si es heredada / extendida por otra clase, puede ser muy útil. Pero por sí mismo, es inútil, ya que no puede tener objetos. Las clases abstractas pueden ser elementos constructivos de las clases finales.

La clase final es un grupo de objetos completos, que se pueden usar, pero no se pueden modificar. Saben exactamente cómo trabajar y qué hacer. Por ejemplo, soy una caja que siempre va a la dirección especificada durante su construcción:

final class DirectBox implements Package {
  private final String to;
  public DirectBox(String addr) {
    this.to = addr;
  }
  @Override
  public String address() {
    return this.to;
  }
}

En la mayoría de los lenguajes, como Java o C ++, es posible tener solo una clase , ni abstracta ni final. Tal clase puede ser heredada y puede ser instanciada. Sin embargo, no creo que esto esté estrictamente en línea con el paradigma orientado a objetos.

Una vez más, comparar interfaces con clases abstractas no es correcto.


La forma más corta de resumirlo es que una interface es:

  1. Totalmente abstracto, aparte de static métodos por default y static ; Si bien tiene definiciones (firmas de métodos + implementaciones) para static métodos default y static , solo tiene declaraciones (firmas de métodos) para otros métodos.
  2. Sujeto a reglas más laxas que las clases (una clase puede implementar múltiples interface y una interface puede heredar de múltiples interface ). Todas las variables son implícitamente constantes, ya sea que se especifiquen como public static final o no. Todos los miembros son implícitamente public , ya sean especificados como tales o no.
  3. Generalmente se utiliza como garantía de que la clase implementadora tendrá las características especificadas y / o será compatible con cualquier otra clase que implemente la misma interfaz.

Mientras tanto, una clase abstract es:

  1. En cualquier lugar, desde totalmente abstracto hasta totalmente implementado, con una tendencia a tener uno o más métodos abstract . Puede contener tanto declaraciones como definiciones, con declaraciones marcadas como abstract .
  2. Una clase de pleno derecho y sujeta a las reglas que rigen a otras clases (solo puede heredar de una clase), con la condición de que no se pueda crear una instancia (porque no hay garantía de que se haya implementado por completo). Puede tener variables miembro no constantes.Puede implementar el control de acceso de los miembros, la restricción de los miembros como protected, private, o paquete privada (no especificado).
  3. Generalmente se utiliza para proporcionar la mayor parte de la implementación que pueden compartir varias subclases, o para proporcionar la mayor parte de la implementación que el programador pueda proporcionar.

O, si queremos hervir todo abajo a una sola frase: Una interfacees lo que la clase que implementa tiene , sino una abstractclase es lo que la subclase es .


Las diferencias técnicas clave entre una clase abstracta y una interface son:

  • Las clases abstractas pueden tener constantes, miembros, apéndices de métodos (métodos sin cuerpo) y métodos definidos , mientras que las interfaces solo pueden tener constantes y apéndices de métodos .

  • Los métodos y los miembros de una clase abstracta se pueden definir con cualquier visibilidad , mientras que todos los métodos de una interfaz deben definirse como public (se definen públicos de forma predeterminada).

  • Al heredar una clase abstracta, una clase secundaria concreta debe definir los métodos abstractos , mientras que una clase abstracta puede extender otra clase abstracta y los métodos abstractos de la clase principal no tienen que ser definidos.

  • De manera similar, una interfaz que extiende otra interfaz no es responsable de implementar métodos desde la interfaz principal. Esto se debe a que las interfaces no pueden definir ninguna implementación.

  • Una clase secundaria solo puede ampliar una clase (abstracta o concreta), mientras que una interfaz puede ampliarse o una clase puede implementar otras múltiples interfaces .

  • Una clase secundaria puede definir métodos abstractos con la misma o menos visibilidad restrictiva , mientras que una clase que implementa una interfaz debe definir los métodos con la misma visibilidad (pública).


No quiero resaltar las diferencias, que ya se han dicho en muchas respuestas (con respecto a los modificadores finales estáticos públicos para variables en interfaz y soporte para métodos protegidos, privados en clases abstractas)

En términos simples, me gustaría decir:

Interfaz: para implementar un contrato por múltiples objetos no relacionados.

clase abstracta: para implementar el mismo o diferente comportamiento entre múltiples objetos relacionados

De la documentation Oracle

Considere usar clases abstractas si:

  1. Desea compartir código entre varias clases estrechamente relacionadas.
  2. Usted espera que las clases que extiendan su clase abstracta tengan muchos métodos o campos comunes, o que requieran modificadores de acceso que no sean públicos (como protegidos y privados).
  3. Desea declarar campos no estáticos o no finales.

Considere usar interfaces si:

  1. Usted espera que las clases no relacionadas implementen su interfaz. Por ejemplo, muchos objetos no relacionados pueden implementar una interfaz Serializable .
  2. Desea especificar el comportamiento de un tipo de datos en particular, pero no le preocupa quién implementa su comportamiento.
  3. Desea aprovechar la herencia de tipo múltiple.

La clase abstracta establece que "es una" relación con las clases concretas. La interfaz proporciona "tiene una" capacidad para las clases.

Si está buscando Java como lenguaje de programación, aquí hay algunas actualizaciones más:

Java 8 ha reducido la brecha entre la interface y las clases abstract en cierta medida al proporcionar una función de método default . Una interfaz que no tiene una implementación para un método ya no es válida ahora.

Consulte esta page documentación para más detalles.

Eche un vistazo a esta pregunta de SE para ver ejemplos de código para comprender mejor.

¿Cómo debería haber explicado la diferencia entre una interfaz y una clase abstracta?


Realmente no es la respuesta a la pregunta original, pero una vez que tenga la respuesta a la diferencia entre ellas, ingresará el dilema de cuándo usar cada: ¿ Cuándo usar interfaces o clases abstractas? ¿Cuándo usar ambos?

Tengo un conocimiento limitado de OOP, pero ver las interfaces como equivalente de un adjetivo en gramática ha funcionado para mí hasta ahora (¡corríjame si este método es falso!). Por ejemplo, los nombres de las interfaces son como atributos o capacidades que puede otorgar a una clase, y una clase puede tener muchas de ellas: ISerializable, ICountable, IList, ICacheable, IHappy, ...


Si tiene algunos métodos comunes que pueden ser utilizados por varias clases, vaya a clases abstractas. De lo contrario, si desea que las clases sigan algún modelo definido, vaya a las interfaces.

Los siguientes ejemplos demuestran esto.

Clase abstracta en Java:

abstract class animals
{
    // They all love to eat. So let's implement them for everybody
    void eat()
    {
        System.out.println("Eating...");
    }
    // The make different sounds. They will provide their own implementation.
    abstract void sound();
}

class dog extends animals
{
    void sound()
    {
        System.out.println("Woof Woof");
    }
}

class cat extends animals
{
    void sound()
    {
        System.out.println("Meoww");
    }
}

A continuación se muestra una implementación de interfaz en Java:

interface Shape
{
    void display();
    double area();
}

class Rectangle implements Shape 
{
    int length, width;
    Rectangle(int length, int width)
    {
        this.length = length;
        this.width = width;
    }
    @Override
    public void display() 
    {
        System.out.println("****\n* *\n* *\n****"); 
    }
    @Override
    public double area() 
    {
        return (double)(length*width);
    }
} 

class Circle implements Shape 
{
    double pi = 3.14;
    int radius;
    Circle(int radius)
    {
        this.radius = radius;
    }
    @Override
    public void display() 
    {
        System.out.println("O"); // :P
    }
    @Override
    public double area() 
    { 
        return (double)((pi*radius*radius)/2);
    }
}

Algunos puntos clave importantes en pocas palabras:

  1. Las variables declaradas en la interfaz de Java son, por defecto, finales. Las clases abstractas pueden tener variables no finales.

  2. Las variables declaradas en la interfaz de Java son por defecto estáticas. Las clases abstractas pueden tener variables no estáticas.

  3. Los miembros de una interfaz Java son públicos por defecto. Una clase abstracta de Java puede tener los sabores habituales de los miembros de la clase como privado, protegido, etc.


Una Interfaz contiene solo la definición / firma de funcionalidad, y si tenemos alguna funcionalidad común así como firmas comunes, entonces necesitamos usar una clase abstracta. Al utilizar una clase abstracta, podemos proporcionar comportamiento y funcionalidad al mismo tiempo. Otro desarrollador que hereda una clase abstracta puede usar esta funcionalidad fácilmente, ya que solo necesitarían completar los espacios en blanco.

Tomado de:

http://www.dotnetbull.com/2011/11/difference-between-abstract-class-and.html

http://www.dotnetbull.com/2011/11/what-is-abstract-class-in-c-net.html http://www.dotnetbull.com/2011/11/what-is-interface-in-c-net.html


Una explicación se puede encontrar aquí: http://www.developer.com/lang/php/article.php/3604111/PHP-5-OOP-Interfaces-Abstract-Classes-and-the-Adapter-Pattern.htm

Una clase abstracta es una clase que solo es implementada parcialmente por el programador. Puede contener uno o más métodos abstractos. Un método abstracto es simplemente una definición de función que sirve para decirle al programador que el método debe implementarse en una clase secundaria.

Una interfaz es similar a una clase abstracta; de hecho, las interfaces ocupan el mismo espacio de nombres que las clases y las clases abstractas. Por ese motivo, no puede definir una interfaz con el mismo nombre que una clase. Una interfaz es una clase totalmente abstracta; ninguno de sus métodos está implementado y, en lugar de una subclase de clase, se dice que implementa esa interfaz.

De todos modos me parece algo confusa esta explicación de interfaces. Una definición más común es: Una interfaz define un contrato que deben cumplir las clases implementadoras. Una definición de interfaz consiste en firmas de miembros públicos, sin ningún código de implementación.


Diferencias entre la clase abstracta y la interfaz en nombre de la implementación real.

Interfaz : es una palabra clave y se usa para definir la plantilla o el plano azul de un objeto y obliga a todas las subclases a seguir el mismo prototipo, ya que, como implementación, todas las subclases son libres de implementar la funcionalidad según es requisito

Algunos de los otros casos de uso donde deberíamos usar interfaz.

La comunicación entre dos objetos externos (integración de terceros en nuestra aplicación) se realiza a través de la interfaz aquí La interfaz funciona como contrato.

Clase abstracta: Resumen, es una palabra clave y cuando usamos esta palabra clave antes que cualquier clase, se convierte en clase abstracta. Se usa principalmente cuando necesitamos definir la plantilla, así como algunas funciones predeterminadas de un objeto, seguidas de todas las las subclases y de esta manera elimina el código redundante y uno más de los casos de uso donde podemos usar clases abstractas , como queremos que otras clases no puedan instanciar directamente un objeto de la clase, solo las clases derivadas pueden usar la funcionalidad.

Ejemplo de clase abstracta:

 public abstract class DesireCar
  {

 //It is an abstract method that defines the prototype.
     public abstract void Color();

  // It is a default implementation of a Wheel method as all the desire cars have the same no. of wheels.   
 // and hence no need to define this in all the sub classes in this way it saves the code duplicasy     

  public void Wheel() {          

               Console.WriteLine("Car has four wheel");
                }
           }


    **Here is the sub classes:**

     public class DesireCar1 : DesireCar
        {
            public override void Color()
            {
                Console.WriteLine("This is a red color Desire car");
            }
        }

        public class DesireCar2 : DesireCar
        {
            public override void Color()
            {
                Console.WriteLine("This is a red white Desire car");
            }
        }

Ejemplo de interfaz:

  public interface IShape
        {
          // Defines the prototype(template) 
            void Draw();
        }


  // All the sub classes follow the same template but implementation can be different.

    public class Circle : IShape
    {
        public void Draw()
        {
            Console.WriteLine("This is a Circle");
        }
    }

    public class Rectangle : IShape
    {
        public void Draw()
        {
            Console.WriteLine("This is a Rectangle");
        }
    }

En una interfaz, todos los métodos deben ser solo definiciones, no se debe implementar uno solo.

Pero en una clase abstracta debe haber un método abstracto con solo definición, pero otros métodos también pueden estar en la clase abstracta con implementación ...


Por definición, las interfaces no pueden tener una implementación para ningún método, y las variables de miembros no se pueden inicializar.

Sin embargo, las clases abstractas pueden tener métodos implementados y variables miembro inicializadas.

Use clases abstractas cuando espere cambios en su contrato, es decir, digamos que en el futuro podría necesitar agregar un nuevo método.

En esta situación, si decide utilizar una interfaz, cuando se cambia la interfaz para incluir la interfaz, su aplicación se interrumpirá cuando descargue la nueva interfaz dll.

Para leer en detalle, visite la diferencia entre clase abstracta y una interfaz


Leí una explicación simple pero efectiva de la clase abstracta y la interfaz en php.net

Que es la siguiente.

Una interfaz es como un protocolo. No designa el comportamiento del objeto; Designa cómo su código le dice a ese objeto que actúe. Una interfaz sería como el idioma inglés: definir una interfaz define cómo su código se comunica con cualquier objeto que implementa esa interfaz.

Una interfaz es siempre un acuerdo o una promesa. Cuando una clase dice "Implemento la interfaz Y", dice "Prometo tener los mismos métodos públicos que cualquier objeto con la interfaz Y".

Por otro lado, una clase abstracta es como una clase parcialmente construida. Es muy parecido a un documento con espacios en blanco para completar. Puede que esté usando inglés, pero eso no es tan importante como el hecho de que parte del documento ya está escrito.

Una clase abstracta es la base de otro objeto. Cuando una clase dice "Extiendo la clase abstracta Y", está diciendo "Utilizo algunos métodos o propiedades ya definidos en esta otra clase llamada Y".

Entonces, considere el siguiente PHP:

<?php
class X implements Y { } // this is saying that "X" agrees to speak language "Y" with your code.

class X extends Y { } // this is saying that "X" is going to complete the partial class "Y".
?>

Su clase implementaría una interfaz particular si distribuyera una clase para que la usen otras personas. La interfaz es un acuerdo para tener un conjunto específico de métodos públicos para su clase.

Le pediría a su clase extender una clase abstracta si usted (o alguien más) escribió una clase que ya tenía algunos métodos escritos que desea usar en su nueva clase.

Estos conceptos, aunque fáciles de confundir, son específicamente diferentes y distintos. Para todos los propósitos, si usted es el único usuario de cualquiera de sus clases, no necesita implementar interfaces.


Muchos desarrolladores junior cometen el error de pensar en interfaces, clases abstractas y concretas como ligeras variaciones de la misma cosa, y eligen uno de ellos exclusivamente por razones técnicas: ¿Necesito herencia múltiple? ¿Necesito algún lugar para poner métodos comunes? ¿Necesito molestarme con algo más que una clase concreta? Esto es incorrecto, y oculto en estas preguntas es el problema principal: "Yo" . Cuando escribe un código para usted mismo, raramente piensa en otros desarrolladores presentes o futuros que trabajen en o con su código.

Interfaces y clases abstractas, aunque aparentemente similares desde un punto de vista técnico, tienen significados y propósitos completamente diferentes.

Resumen

  1. Una interfaz define un contrato que alguna implementación cumplirá para usted .

  2. Una clase abstracta proporciona un comportamiento predeterminado que su implementación puede reutilizar.

Resumen alternativo

  1. Una interfaz es para definir APIs públicas.
  2. Una clase abstracta es para uso interno y para definir SPIs.

Sobre la importancia de ocultar detalles de implementación.

Una clase concreta hace el trabajo real, de una manera muy específica. Por ejemplo, ArrayListusa un área contigua de memoria para almacenar una lista de objetos de una manera compacta que ofrece acceso aleatorio rápido, iteración y cambios en el lugar, pero es terrible en las inserciones, eliminaciones y, ocasionalmente, incluso en adiciones; mientras tanto, a LinkedListutiliza nodos de doble enlace para almacenar una lista de objetos, que en su lugar ofrece iteración rápida, cambios in situ e inserción / eliminación / adición, pero es terrible en el acceso aleatorio. Estos dos tipos de listas están optimizados para diferentes casos de uso, y es muy importante cómo los va a utilizar. Cuando esté tratando de exprimir el rendimiento de una lista con la que está interactuando intensamente, y cuando elija el tipo de lista que le corresponda, debe elegir con cuidado cuál de ellas está creando.

Por otro lado, a los usuarios de alto nivel de una lista realmente no les importa cómo se implementa, y deben estar aislados de estos detalles. Imaginemos que Java no expuso la Listinterfaz, sino que solo tenía una Listclase concreta que en realidad LinkedListes lo que es ahora. Todos los desarrolladores de Java habrían adaptado su código para que se ajustara a los detalles de la implementación: evitar el acceso aleatorio, agregar un caché para acelerar el acceso o simplemente ArrayListvolver a implementarlo por su cuenta, aunque sería incompatible con todos los demás códigos con los que realmente funciona List. Eso sería terrible ... Pero ahora imagine que los maestros de Java realmente se dan cuenta de que una lista enlazada es terrible para la mayoría de los casos de uso reales, y decidió cambiar a una lista de arreglos para su únicaListclase disponible Esto afectaría el rendimiento de cada programa Java en el mundo, y la gente no estaría contenta con él. Y el principal culpable es que los detalles de la implementación estaban disponibles, y los desarrolladores asumieron que esos detalles son un contrato permanente en el que pueden confiar. Es por esto que es importante ocultar los detalles de la implementación y solo definir un contrato abstracto. Este es el propósito de una interfaz: definir qué tipo de entrada acepta un método y qué tipo de salida se espera, sin exponer todas las agallas que podrían tentar a los programadores a modificar su código para que se ajuste a los detalles internos que podrían cambiar con cualquier actualización futura .

Una clase abstracta está en el medio entre interfaces y clases concretas. Se supone que ayuda a las implementaciones a compartir código común o aburrido. Por ejemplo, AbstractCollectionproporciona implementaciones básicas para isEmptyel tamaño basado en 0, containscomo iterar y comparar, addAllcomo repetido add, etc. Esto permite que las implementaciones se centren en las partes cruciales que las diferencian: cómo almacenar y recuperar datos.

APIs versus SPIs

Las interfaces son puertas de enlace de baja cohesión entre diferentes partes del código. Permiten que las bibliotecas existan y evolucionen sin interrumpir a cada usuario de la biblioteca cuando algo cambia internamente. Se llama interfaz de programación de aplicaciones , no clases de programación de aplicaciones. En una escala más pequeña, también permiten que múltiples desarrolladores colaboren con éxito en proyectos a gran escala, separando diferentes módulos a través de interfaces bien documentadas.

Las clases abstractas son ayudantes de alta cohesión que se utilizarán al implementar una interfaz, asumiendo algún nivel de detalles de implementación. Alternativamente, las clases abstractas se utilizan para definir SPI, interfaces de proveedor de servicios.

La diferencia entre una API y un SPI es sutil, pero importante: para una API, el enfoque está en quién lo usa , y para un SPI, el enfoque está en quién lo implementa .

Agregar métodos a una API es fácil, todos los usuarios existentes de la API seguirán compilando. Añadir métodos a un SPI es difícil, ya que cada proveedor de servicios (implementación concreta) tendrá que implementar los nuevos métodos. Si se usan interfaces para definir un SPI, un proveedor tendrá que lanzar una nueva versión cada vez que cambie el contrato de SPI. Si se usan clases abstractas en su lugar, los nuevos métodos podrían definirse en términos de métodos abstractos existentes, o como throw not implemented exceptiontalones vacíos , que al menos permitirán que una versión anterior de una implementación de servicio aún se compile y ejecute.

Una nota sobre Java 8 y métodos por defecto.

Aunque Java 8 introdujo métodos predeterminados para las interfaces, lo que hace que la línea entre las interfaces y las clases abstractas sea aún más confusa, no fue así para que las implementaciones puedan reutilizar el código, sino para facilitar el cambio de las interfaces que sirven como API y como SPI (o se utilizan incorrectamente para definir SPI en lugar de clases abstractas).

¿Cuál usar?

  1. ¿Se supone que la cosa debe ser usada públicamente por otras partes del código, o por otro código externo? Agregue una interfaz para ocultar los detalles de la implementación del contrato abstracto público, que es el comportamiento general de la cosa.
  2. ¿Es la cosa algo que se supone que tiene múltiples implementaciones con mucho código en común? Haga una interfaz y una implementación abstracta e incompleta.
  3. ¿Habrá alguna vez una sola implementación y nadie más la usará? Solo hazlo una clase concreta.
    1. "Ever" es mucho tiempo, puedes jugar de forma segura y aún así agregar una interfaz encima.

Un corolario: el revés a menudo se realiza incorrectamente: cuando se usa una cosa , siempre intente usar la clase / interfaz más genérica que realmente necesita. En otras palabras, no declare sus variables como ArrayList theList = new ArrayList(), a menos que realmente tenga una dependencia muy fuerte de que sea una lista de matriz , y ningún otro tipo de lista la cortaría por usted. Utilice en su List theList = new ArrayListlugar, o incluso Collection theCollection = new ArrayListsi el hecho de que sea una lista, y no cualquier otro tipo de colección en realidad no importa.


Puedes encontrar una clara diferencia entre la interfaz y la clase abstracta.

Interfaz

  • La interfaz solo contiene métodos abstractos.
  • Forzar a los usuarios a implementar todos los métodos cuando implementa la interfaz.
  • Contiene solo variables finales y estáticas.
  • Declara el uso de la palabra clave de la interfaz.
  • Todos los métodos de una interfaz deben definirse como públicos.
  • Una interfaz puede extenderse o una clase puede implementar varias otras interfaces.

Clase abstracta

  • La clase abstracta contiene métodos abstractos y no abstractos.

  • No obliga a los usuarios a implementar todos los métodos cuando se hereda la clase abstracta.

  • Contiene todo tipo de variables, incluyendo primitivas y no primitivas.

  • Declara utilizando la palabra clave abstracta.

  • Los métodos y los miembros de una clase abstracta se pueden definir con cualquier visibilidad.

  • Una clase infantil solo puede ampliar una clase (abstracta o concreta).





abstract-class