¿Cuándo usar una interfaz en lugar de una clase abstracta y viceversa?

427

Esta puede ser una pregunta genérica de OOP. Quería hacer una comparación genérica entre una interfaz y una clase abstracta en función de su uso.

¿Cuándo querría usar una interfaz y cuándo querría usar una clase abstracta ?

Chirantan
fuente
1
Además de las respuestas a continuación, esta es una buena lista breve de dónde puede preferir las interfaces y dónde no: Cuándo usar las interfaces: msdn.microsoft.com/en-us/library/3b5b8ezk(v=vs.80) .aspx
Anthony
use el resumen cuando no esté seguro de lo que hará la clase. usa la interfaz si es así.
Uğur Gümüşhan
Me interesa ver cuántos desarrolladores, que no trabajan en Microsoft, definen y usan interfaces en su desarrollo diario.
user1451111

Respuestas:

432

Escribí un artículo sobre eso:

Clases abstractas e interfaces

Resumiendo:

Cuando hablamos de clases abstractas, estamos definiendo características de un tipo de objeto; especificando qué es un objeto .

Cuando hablamos de una interfaz y definimos las capacidades que prometemos proporcionar, estamos hablando de establecer un contrato sobre lo que el objeto puede hacer.

Jorge Córdoba
fuente
114
Esta era ery útiles: Interfaces do not express something like "a Doberman is a type of dog and every dog can walk" but more like "this thing can walk". Gracias
aexl
2
Parece que tu enlace está muerto.
Kim Ahlstrøm Meyn Mathiassen
La explicación de Alex a continuación, re: la diferencia entre solo describir las funciones implementadas versus también describir el estado almacenado, parece una mejor respuesta a esta pregunta, porque las diferencias no son solo filosóficas.
Duncan Malashock
1
Duncan Malashock, en realidad no. La respuesta de Jorge es la mejor. La respuesta de Alex se centra en la mecánica, mientras que Jorge se centra más en la semántica.
Nazar Merza
8
Me gusta la declaración antes de su respuesta especificada:Use abstract classes and inheritance if you can make the statement “A is a B”. Use interfaces if you can make the statement “A is capable of [doing] as”
S1r-Lanzelot
433

Una clase abstracta puede tener estado o funcionalidad compartida. Una interfaz es solo una promesa de proporcionar el estado o la funcionalidad. Una buena clase abstracta reducirá la cantidad de código que debe reescribirse porque su funcionalidad o estado pueden compartirse. La interfaz no tiene información definida para ser compartida

Alex
fuente
65
Esta, para mí, es la mejor respuesta aquí y es una pena que no se haya votado más alto. Sí, existen diferencias filosóficas entre los dos conceptos, pero el punto fundamental es que las clases abstractas aseguran que todos los descendientes compartan funcionalidad / estado, donde una interfaz solo asegura un vínculo común.
drharris
3
Por ejemplo, se usa una clase base abstracta para el patrón de diseño del método de plantilla , mientras que se usa una interfaz para el patrón de diseño de la estrategia .
Raedwald
1
Creo que el resumen de Jorge explica la existencia primaria aunque subyacente para ambos, mientras que la respuesta de Alex es la diferencia en los resultados. Desearía poder marcar ambas como las respuestas correctas, pero todavía prefiero la respuesta de Jorge.
Chirantan
Y aquí hay un ejemplo con código.
shaijut
Para mí, esto "Una buena clase abstracta reducirá la cantidad de código que debe reescribirse porque su funcionalidad o estado pueden compartirse". declaración es el núcleo de la respuesta.
Div Tiwari
82

Personalmente, casi nunca tengo la necesidad de escribir clases abstractas.

La mayoría de las veces veo que se usan (mal) las clases abstractas, es porque el autor de la clase abstracta está usando el patrón "Método de plantilla".

El problema con el "Método de plantilla" es que casi siempre es algo reentrante: la clase "derivada" conoce no solo el método "abstracto" de su clase base que está implementando, sino también los métodos públicos de la clase base. , aunque la mayoría de las veces no es necesario llamarlos.

Ejemplo (demasiado simplificado):

abstract class QuickSorter
{
    public void Sort(object[] items)
    {
        // implementation code that somewhere along the way calls:
        bool less = compare(x,y);
        // ... more implementation code
    }
    abstract bool compare(object lhs, object rhs);
}

Así que aquí, el autor de esta clase ha escrito un algoritmo genérico y pretende que las personas lo usen "especializándolo" proporcionando sus propios "ganchos", en este caso, un método de "comparación".

Entonces, el uso previsto es algo como esto:

class NameSorter : QuickSorter
{
    public bool compare(object lhs, object rhs)
    {
        // etc.
    }
}

El problema con esto es que ha unido indebidamente dos conceptos:

  1. Una forma de comparar dos elementos (qué elemento debe ir primero)
  2. Un método para ordenar elementos (es decir, clasificación rápida frente a combinación, etc.)

En el código anterior, teóricamente, el autor del método "comparar" puede volver a llamar al método "Ordenar" de la superclase ... aunque en la práctica nunca querrán o necesitarán hacer esto.

El precio que paga por este acoplamiento innecesario es que es difícil cambiar la superclase, y en la mayoría de los lenguajes OO, es imposible cambiarlo en tiempo de ejecución.

El método alternativo es utilizar el patrón de diseño "Estrategia" en su lugar:

interface IComparator
{
    bool compare(object lhs, object rhs);
}

class QuickSorter
{
    private readonly IComparator comparator;
    public QuickSorter(IComparator comparator)
    {
        this.comparator = comparator;
    }

    public void Sort(object[] items)
    {
        // usual code but call comparator.Compare();
    }
}

class NameComparator : IComparator
{
    bool compare(object lhs, object rhs)
    {
        // same code as before;
    }
}

Así que observe ahora: todo lo que tenemos son interfaces e implementaciones concretas de esas interfaces. En la práctica, realmente no necesitas nada más para hacer un diseño OO de alto nivel.

Para "ocultar" el hecho de que hemos implementado la "clasificación de nombres" mediante el uso de una clase "QuickSort" y un "NameComparator", aún podríamos escribir un método de fábrica en alguna parte:

ISorter CreateNameSorter()
{
    return new QuickSorter(new NameComparator());
}

Cada vez que tenga una clase abstracta puede hacer esto ... incluso cuando haya una relación natural entrante entre la clase base y la clase derivada, generalmente vale la pena hacerlas explícitas.

Una última reflexión: todo lo que hemos hecho anteriormente es "componer" una función de "Clasificación de nombres" utilizando una función de "Clasificación rápida" y una función de "Comparación de nombres" ... en un lenguaje de programación funcional, este estilo de programación se vuelve aún más natural, con menos código

Paul Hollingsworth
fuente
55
El hecho de que pueda usar clases abstractas o un patrón de método de plantilla no significa que deba evitarlos. El Patrón de estrategia es un patrón diferente para una situación diferente como en este ejemplo, pero hay muchos ejemplos en los que un patrón de plantilla es mucho más adecuado que la Estrategia.
Jorge Córdoba
55
Bueno, en mi experiencia, nunca me encuentro con ellos (situaciones en las que es preferible el método de plantilla) ... o rara vez de todos modos. Y eso es todo "abstracto": soporte de lenguaje para el patrón de diseño del "método de plantilla".
Paul Hollingsworth
Ok, lo usé una vez para un sistema experto en el que el proceso era algo así como: obtener 1. FillTheParameters, 2. Hacer el producto vectorial entre ellos, 3. Para cada resultado de cálculo de par, 4. Unir los resultados, donde los pasos 1 y 3 donde delegado y 2 y 4 implementado en la clase base.
Jorge Córdoba
10
Encuentro que casi cualquier uso de clases abstractas es más difícil de entender. Pensar en términos de cuadros que se comunican entre sí en lugar de las relaciones de herencia es más fácil (para mí) ... Pero también estoy de acuerdo en que los lenguajes OO actuales fuerzan demasiado a los estándares ... Funcional será la forma de superar OO
Paul Hollingsworth
44
El ejemplo de mal uso es bastante trivial. Raramente se reduce a una funcionalidad despojada tan agradable como comparar. Mucho más comunes son las situaciones en las que hay alguna funcionalidad predeterminada que las clases derivadas reemplazan o extienden (y en este último caso es perfectamente válido llamar a la función de clase base). En su ejemplo, no hay una funcionalidad predeterminada, por lo que el uso de la clase abstracta no tiene justificación.
SomeWittyUsername
41

Si estás viendo Java como lenguaje OOP,

"La interfaz no proporciona la implementación del método " ya no es válido con el lanzamiento de Java 8. Ahora Java proporciona implementación en la interfaz para los métodos predeterminados.

En términos simples, me gustaría usar

interfaz: para implementar un contrato por varios objetos no relacionados. Proporciona lacapacidad" TIENE A ".

clase abstracta: para implementar el mismo comportamiento o diferente entre múltiples objetos relacionados. Establece la relación " ES A ".

El sitio web de Oracle proporciona diferencias clave entre interfacey la abstractclase.

Considere usar clases abstractas si:

  1. Desea compartir código entre varias clases estrechamente relacionadas.
  2. Espera que las clases que extienden su clase abstracta tengan muchos métodos o campos comunes, o 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. Espera que clases no relacionadas implementen su interfaz. Por ejemplo, muchos objetos no relacionados pueden implementar la Serializableinterfaz.
  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 múltiple de tipo.

Ejemplo:

Clase abstracta ( relación IS A )

Reader es una clase abstracta.

BufferedReader es unReader

FileReader es unReader

FileReadery BufferedReaderse usan para un propósito común: leer datos, y están relacionados a través de la Readerclase.

Interfaz ( capacidad HAS A )

Serializable es una interfaz.

Suponga que tiene dos clases en su aplicación, que están implementando la Serializableinterfaz

Employee implements Serializable

Game implements Serializable

Aquí no puede establecer ninguna relación a través de la Serializableinterfaz entre Employeey Game, que están destinados a diferentes propósitos. Ambos son capaces de serializar el estado y la comparación termina allí.

Echa un vistazo a estas publicaciones:

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

Ravindra babu
fuente
40

Bien, después de haber "asimilado" esto yo mismo, aquí está en términos simples (siéntase libre de corregirme si me equivoco), sé que este tema es demasiado viejo, pero alguien más podría tropezar con él algún día ...

Las clases abstractas le permiten crear un plano, y además le permiten CONSTRUIR (implementar) propiedades y métodos que desea que TODOS sus descendientes posean.

Por otro lado, una interfaz solo le permite declarar que desea que existan propiedades y / o métodos con un nombre determinado en todas las clases que lo implementan, pero no especifica cómo debe implementarlo. Además, una clase puede implementar MUCHAS interfaces, pero solo puede extender UNA clase abstracta. Una interfaz es más una herramienta arquitectónica de alto nivel (que se vuelve más clara si comienzas a comprender patrones de diseño): un Resumen tiene un pie en ambos campos y también puede realizar parte del trabajo sucio.

¿Por qué usar uno sobre el otro? El primero permite una definición más concreta de descendientes; el segundo permite un mayor polimorfismo . Este último punto es importante para el usuario / codificador final, que puede utilizar esta información para implementar el AP I (interfaz) en una variedad de combinaciones / formas para satisfacer sus necesidades.

Creo que este fue el momento "bombilla" para mí: piense en las interfaces menos desde la perspectiva del autor y más desde la de cualquier codificador que venga más adelante en la cadena que agregue implementación a un proyecto o extienda una API.

sunwukung
fuente
para construir sobre esto: un objeto que implementa una interfaz adquiere su TIPO. Esto es crucial Por lo tanto, puede pasar diferentes variaciones de la interfaz a una clase, pero refiérase a ellas (y sus métodos) CON EL NOMBRE DE TIPO DE LA INTERFAZ. Por lo tanto, elimina la necesidad de un interruptor o un bucle if / else. Pruebe este tutorial sobre el tema: demuestra el uso de una interfaz a través del Patrón de estrategia. phpfreaks.com/tutorial/design-patterns---strategy-and-bridge/…
sunwukung
Estoy totalmente de acuerdo con su momento de bombilla: "API (interfaz) en una variedad de combinaciones / formas para satisfacer sus necesidades". Muy, muy buen punto para hacer.
Trevor Boyd Smith
39

Mis dos centavos:

Una interfaz básicamente define un contrato, que cualquier clase de implementación debe cumplir (implementar los miembros de la interfaz). No contiene ningún código.

Por otro lado, una clase abstracta puede contener código, y puede haber algunos métodos marcados como abstractos que una clase heredada debe implementar.

Las raras situaciones en las que he usado clases abstractas es cuando tengo alguna funcionalidad predeterminada de la que la clase heredadora podría no ser interesante anular, por ejemplo, una clase base abstracta, de la que heredan algunas clases especializadas.

Ejemplo (uno muy rudimentaria!): Consideremos una llamada de atención al cliente de clase base que tiene métodos abstractos como CalculatePayment(), CalculateRewardPoints()y algunos métodos no abstractos como GetName(), SavePaymentDetails().

Especializada como clases RegularCustomer y GoldCustomerheredará de la Customerclase base y poner en práctica su propio CalculatePayment()y CalculateRewardPoints()método de la lógica, pero re-utilizar el GetName()y SavePaymentDetails()métodos.

Puede agregar más funcionalidad a una clase abstracta (es decir, métodos no abstractos) sin afectar las clases secundarias que usaban una versión anterior. Mientras que agregar métodos a una interfaz afectaría a todas las clases que lo implementan, ya que ahora necesitarían implementar los miembros de la interfaz recientemente agregados.

Una clase abstracta con todos los miembros abstractos sería similar a una interfaz.

PreethaA
fuente
1
+1 para "Puede agregar más funcionalidad a una clase abstracta (es decir, métodos no abstractos) sin afectar las clases secundarias que usaban una versión anterior. Mientras que agregar métodos a una interfaz afectaría a todas las clases que la implementan, ya que ahora necesitarían implementar los miembros de la interfaz recientemente agregados ".
Div Tiwari
las interfaces pueden tener métodos "predeterminados", por lo que no tener un método implícito en las interfaces es una idea incorrecta. La relación IS-A "padre a hijo" es la clave aquí. Además, "Atributos compartidos" frente a "Propiedades compartidas". por ejemplo, perro iS-A Animal. Pero un perro también puede "caminar"
ha9u63ar
30

Cuándo hacer qué es algo muy simple si tienes el concepto claro en tu mente.

Las clases abstractas se pueden derivar, mientras que las interfaces se pueden implementar. Hay alguna diferencia entre los dos. Cuando deriva una clase abstracta, la relación entre la clase derivada y la clase base es una relación 'es una'. por ejemplo, un perro es un animal, una oveja es un animal, lo que significa que una clase derivada hereda algunas propiedades de la clase base.

Mientras que para la implementación de interfaces, la relación es "puede ser". Por ejemplo, un perro puede ser un perro espía. Un perro puede ser un perro de circo. Un perro puede ser un perro de raza. Lo que significa que implementa ciertos métodos para adquirir algo.

Espero estar claro.

Aamir
fuente
11

1. Si está creando algo que proporciona una funcionalidad común a clases no relacionadas, use una interfaz.

2. Si está creando algo para objetos que están estrechamente relacionados en una jerarquía, use una clase abstracta.

kuttychutty
fuente
7

Creo que la forma más sucinta de decirlo es la siguiente:

Propiedades compartidas => clase abstracta.
Funcionalidad compartida => interfaz.

Y para decirlo de manera menos sucinta ...

Ejemplo de clase abstracta:

public abstract class BaseAnimal
{
    public int NumberOfLegs { get; set; }

    protected BaseAnimal(int numberOfLegs)
    {
        NumberOfLegs = numberOfLegs;
    }
}

public class Dog : BaseAnimal
{
    public Dog() : base(4) { }
}

public class Human : BaseAnimal 
{
    public Human() : base(2) { }
}

Dado que los animales tienen una propiedad compartida - número de patas en este caso - tiene sentido hacer una clase abstracta que contenga esta propiedad compartida. Esto también nos permite escribir código común que opera en esa propiedad. Por ejemplo:

public static int CountAllLegs(List<BaseAnimal> animals)
{
    int legCount = 0;
    foreach (BaseAnimal animal in animals)
    {
        legCount += animal.NumberOfLegs;
    }
    return legCount;
}

Ejemplo de interfaz:

public interface IMakeSound
{
    void MakeSound();
}

public class Car : IMakeSound
{
    public void MakeSound() => Console.WriteLine("Vroom!");
}

public class Vuvuzela : IMakeSound
{
    public void MakeSound() => Console.WriteLine("VZZZZZZZZZZZZZ!");        
}

Tenga en cuenta aquí que Vuvuzelas y Cars son cosas completamente diferentes, pero tienen una funcionalidad compartida: hacer un sonido. Por lo tanto, una interfaz tiene sentido aquí. Además, permitirá a los programadores agrupar cosas que producen sonidos en una interfaz común, IMakeSounden este caso. Con este diseño, podría escribir el siguiente código:

List<IMakeSound> soundMakers = new List<ImakeSound>();
soundMakers.Add(new Car());
soundMakers.Add(new Vuvuzela());
soundMakers.Add(new Car());
soundMakers.Add(new Vuvuzela());
soundMakers.Add(new Vuvuzela());

foreach (IMakeSound soundMaker in soundMakers)
{
    soundMaker.MakeSound();
}

¿Puedes decir qué produciría eso?

Por último, puedes combinar los dos.

Ejemplo combinado:

public interface IMakeSound
{
    void MakeSound();
}

public abstract class BaseAnimal : IMakeSound
{
    public int NumberOfLegs { get; set; }

    protected BaseAnimal(int numberOfLegs)
    {
        NumberOfLegs = numberOfLegs;
    }

    public abstract void MakeSound();
}

public class Cat : BaseAnimal
{
    public Cat() : base(4) { }

    public override void MakeSound() => Console.WriteLine("Meow!");
}

public class Human : BaseAnimal 
{
    public Human() : base(2) { }

    public override void MakeSound() => Console.WriteLine("Hello, world!");
}

Aquí, estamos exigiendo que todos BaseAnimalemitan un sonido, pero aún no sabemos su implementación. En tal caso, podemos abstraer la implementación de la interfaz y delegar su implementación a sus subclases.

Un último punto, ¿recuerda cómo en el ejemplo de clase abstracta pudimos operar sobre las propiedades compartidas de diferentes objetos y en el ejemplo de interfaz pudimos invocar la funcionalidad compartida de diferentes objetos? En este último ejemplo, podríamos hacer ambas cosas.

Domn Werner
fuente
7

¿Cuándo preferir una clase abstracta sobre una interfaz?

  1. Si uno planea actualizar una clase base a lo largo de la vida de un programa / proyecto, es mejor permitir que la clase base sea una clase abstracta
  2. Si uno está tratando de construir una columna vertebral para objetos que están estrechamente relacionados en una jerarquía, es muy beneficioso usar una clase abstracta

¿Cuándo preferir una interfaz sobre la clase abstracta?

  1. Si no se trata de un marco jerárquico masivo, las interfaces serían una excelente opción
  2. Debido a que la herencia múltiple no es compatible con las clases abstractas (problema de diamante), las interfaces pueden salvar el día
Satya
fuente
¿Qué te hizo pensar que una pregunta de casi una década necesitaba una respuesta número 22?
jonrsharpe
3
El mismo tipo de pensamiento que me hizo buscar una respuesta simple a la pregunta.
Satya
1
FWIW, realmente me encanta esta respuesta.
Brent Rittenhouse
6

Las clases pueden heredar de una sola clase base, por lo que si desea usar clases abstractas para proporcionar polimorfismo a un grupo de clases, todas deben heredar de esa clase. Las clases abstractas también pueden proporcionar miembros que ya se han implementado. Por lo tanto, puede garantizar una cierta cantidad de funcionalidad idéntica con una clase abstracta, pero no puede hacerlo con una interfaz.

Aquí hay algunas recomendaciones para ayudarlo a decidir si usar una interfaz o una clase abstracta para proporcionar polimorfismo a sus componentes.

  • Si prevé crear varias versiones de su componente, cree una clase abstracta. Las clases abstractas proporcionan una manera simple y fácil de versionar sus componentes. Al actualizar la clase base, todas las clases heredadas se actualizan automáticamente con el cambio. Las interfaces, por otro lado, no se pueden cambiar una vez creadas de esa manera. Si se requiere una nueva versión de una interfaz, debe crear una interfaz completamente nueva.
  • Si la funcionalidad que está creando será útil en una amplia gama de objetos dispares, use una interfaz. Las clases abstractas deben usarse principalmente para objetos que están estrechamente relacionados, mientras que las interfaces son las más adecuadas para proporcionar una funcionalidad común a clases no relacionadas.
  • Si está diseñando bits pequeños y concisos de funcionalidad, use interfaces. Si está diseñando unidades funcionales grandes, use una clase abstracta.
  • Si desea proporcionar una funcionalidad común e implementada entre todas las implementaciones de su componente, use una clase abstracta. Las clases abstractas le permiten implementar parcialmente su clase, mientras que las interfaces no contienen implementación para ningún miembro.

Copiado de:
http://msdn.microsoft.com/en-us/library/scsyfw1d%28v=vs.71%29.aspx

Mazhar
fuente
No hay nada en UML que impida la herencia de clases múltiples. La herencia múltiple está determinada por un lenguaje de programación, no por UML. Por ejemplo, la herencia de clases múltiples no está permitida en Java y C #, pero sí en C ++.
BobRodes
@BobRodes: hay una serie de características que los marcos orientados a objetos pueden proporcionar en varias combinaciones, pero no en todas las combinaciones. La herencia múltiple generalizada excluye algunas otras combinaciones útiles de características, incluida la capacidad de emitir una referencia directamente a cualquier tipo principal de la instancia real o cualquier tipo de interfaz compatible, y la capacidad de compilar de forma independiente los tipos base y los tipos derivados y unirlos en tiempo de ejecución.
supercat
@supercat Yours es una buena explicación de algunos de los problemas que resultan del uso de la herencia múltiple. Sin embargo, no hay nada en UML que impida la herencia de clases múltiples en un diagrama. Estaba respondiendo a lo anterior "Las clases pueden heredar de una sola clase base ...", que no es así.
BobRodes
@BobRodes: la pregunta fue etiquetada Java. Java incluye las características indicadas y, por lo tanto, está limitado a formas de herencia múltiple que no pueden producir un "diamante mortal" (aunque, de hecho, la forma en que han implementado implementaciones de interfaz predeterminadas hace posible el diamante mortal).
supercat
@supercat Oh, está bien. Por lo general, no miro las etiquetas de Java, así que en el momento en que escribí que al menos pensaba que estaba comentando una respuesta UML. En cualquier caso, estoy de acuerdo con tu comentario.
BobRodes
3

Considere usar clases abstractas si alguna de estas afirmaciones se aplica a su situación:

  1. Desea compartir código entre varias clases estrechamente relacionadas.
  2. Espera que las clases que extienden su clase abstracta tengan muchos métodos o campos comunes o requieran modificadores de acceso que no sean públicos (como protegidos y privados).
  3. Desea declarar campos no estáticos o no finales. Esto le permite definir métodos que pueden acceder y modificar el estado del objeto al que pertenecen.

Considere usar interfaces si alguna de estas declaraciones se aplica a su situación:

  1. Espera que clases no relacionadas implementen su interfaz. Por ejemplo, las interfaces Comparable y Cloneable son implementadas por muchas clases no relacionadas.
  2. Desea especificar el comportamiento de un tipo de datos en particular, pero no le preocupa quién implementa su comportamiento.
  3. Desea aprovechar las múltiples herencias.

Fuente

Abhijeet Ashok Muneshwar
fuente
2

Las respuestas varían entre idiomas. Por ejemplo, en Java una clase puede implementar (heredar de) múltiples interfaces pero solo heredar de una clase abstracta. Entonces las interfaces le dan más flexibilidad. Pero esto no es cierto en C ++.

Nick Fortescue
fuente
2

Para mí, iría con interfaces en muchos casos. Pero prefiero las clases abstractas en algunos casos.

Las clases en OO generalmente se refieren a la implementación. Utilizo clases abstractas cuando quiero forzar algunos detalles de implementación a los niños que voy con interfaces.

Por supuesto, las clases abstractas son útiles no solo para forzar la implementación sino también para compartir algunos detalles específicos entre muchas clases relacionadas.

La VloZ Merrill
fuente
1

Utilice una clase abstracta si desea proporcionar algunas implementaciones básicas.

Sebastian
fuente
1
Gracias sebastian Pero, ¿y si no necesito tener una implementación básica? ¿Una clase abstracta y una interfaz no serán las mismas si esta es la única diferencia entre ellas? ¿Por qué hay una diferencia?
Chirantan
1
Debido a que algunos lenguajes no tienen interfaces, C ++.
jmucchiello
1

en java puede heredar de una clase (abstracta) para "proporcionar" funcionalidad y puede implementar muchas interfaces para "garantizar" la funcionalidad

Peter Miehle
fuente
Sugerencia: si desea heredar de una clase abstracta y una interfaz, asegúrese de que la clase abstracta implemente la interfaz
Andreas Niedermair
1

Puramente sobre la base de la herencia, usaría un resumen en el que define relaciones abstractas claramente descendientes (es decir, animal-> gato) y / o requiere la herencia de propiedades virtuales o no públicas, especialmente el estado compartido (que las interfaces no pueden soportar )

Sin embargo, debe intentar favorecer la composición (a través de la inyección de dependencia) sobre la herencia, y tenga en cuenta que las interfaces que son contratos admiten pruebas unitarias, separación de inquietudes y herencia múltiple (variando el idioma) de una manera que los resúmenes no pueden.

annakata
fuente
1

Una ubicación interesante donde las interfaces funcionan mejor que las clases abstractas es cuando necesita agregar funcionalidad adicional a un grupo de objetos (relacionados o no relacionados). Si no puede darles una clase abstracta base (por ejemplo, son sealedo ya tienen un padre), puede darles una interfaz ficticia (vacía) y luego simplemente escribir métodos de extensión para esa interfaz.

Dmitri Nesteruk
fuente
0

Esta puede ser una llamada muy difícil de hacer ...

Un puntero que puedo dar: un objeto puede implementar muchas interfaces, mientras que un objeto solo puede heredar una clase base (en un lenguaje OO moderno como C #, sé que C ++ tiene herencia múltiple, pero ¿no está mal visto?)

Malla
fuente
La herencia múltiple permite que Mixin se implemente aparentemente, Mixin bien escrito es muy fácil de trabajar pero muy difícil de encontrar y difícil de escribir sin quedarse corto en algún lugar. Los mixin son bastante geniales en general, aunque en mi opinión.
Martijn Laarman el
En realidad no lo hice, la herencia múltiple es de hecho un debate seguro entre nosotros, geeks, no veo absolutamente ninguna razón para rechazar. De hecho, he votado tu respuesta.
Martijn Laarman el
El único punto que intenté hacer es que también es posible mezclar en lenguajes con herencia única (C #, PHP, javascript) pero a través del comportamiento hacky o sintaxis hortera. Me encanta Mixin cuando funcionan, pero todavía no estoy decidida sobre si recibir herencia múltiple o no.
Martijn Laarman el
Esta respuesta es más una diferencia sintáctica que una diferencia de diseño. Creo que está pidiendo una diferencia de diseño
Pramod Setlur
0

Una clase abstracta puede tener implementaciones.

Una interfaz no tiene implementaciones, simplemente define un tipo de contrato.

También puede haber algunas diferencias dependientes del lenguaje: por ejemplo, C # no tiene herencia múltiple, pero se pueden implementar múltiples interfaces en una clase.

Gerrie Schenck
fuente
Cuando dices "una especie de contrato", ¿te refieres a los servicios web?
Chirantan
Técnicamente hablando, los servicios web no funcionan con interfaces. Con contrato quiero decir que el usuario de un objeto sabe qué métodos están presentes en ese objeto. Por ejemplo, una interfaz IMouse tendrá un método Move y un evento de botón izquierdo y derecho del mouse.
Gerrie Schenck el
-1

La regla básica del pulgar es: para "sustantivos" use la clase abstracta y para "verbos" use la interfaz

Por ejemplo: cares una clase abstracta y drivepodemos convertirla en una interfaz.

GANI
fuente
55
Esto no tiene sentido, también podemos poner la funcionalidad de driveen el automóvil, que es una clase abstracta.
Arslan Ali