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

oop - sirve - interfaces poo



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

Esta puede ser una pregunta genérica de POO. Quería hacer una comparación genérica entre una interfaz y una clase abstracta sobre la base de su uso.

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


1. Si está creando algo que proporciona una funcionalidad común a las 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.


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. 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. Esto le permite definir métodos que pueden acceder y modificar el estado del objeto al que pertenecen.

Considere utilizar interfaces si alguna de estas afirmaciones se aplica a su situación:

  1. Usted espera que las 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. Quieres aprovechar las múltiples herencias.

Source


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

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

Y para decirlo de forma 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 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 hacen sonidos juntos bajo una interfaz común: IMakeSound en este caso. Con este diseño, podrías 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 lo que sería la salida?

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í, requerimos que todos los BaseAnimal hagan un sonido, pero todavía 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 con 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.


Cuándo hacer lo que es una cosa muy simple si tiene el concepto claro en su mente.

Las clases abstractas se pueden derivar, mientras que las interfaces se pueden implementar. Hay alguna diferencia entre los dos. Cuando se deriva una clase abstracta, la relación entre la clase derivada y la clase base es "es una relación". por ejemplo, un perro es un animal, una oveja es un animal, lo que significa que una clase derivada está heredando 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 implementas ciertos métodos para adquirir algo.

Espero que quede claro.


De acuerdo, simplemente "arreglé" esto, aquí está en términos sencillos (siéntase libre de corregirme si me equivoco). Sé que este tema es muy bueno, pero alguien más podría encontrarlo un día ...

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

Por otra parte, una interfaz solo le permite declarar que desea que existan propiedades y / o métodos con un nombre dado en todas las clases que lo implementen, 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 empiezas a entender los patrones de diseño): un Resumen tiene un pie en ambos campos y puede realizar parte del trabajo sucio también.

¿Por qué usar uno sobre el otro? El primero permite una definición más concreta de los descendientes, el segundo permite un mayor polimorfismo . Este último punto es importante para el usuario final / codificador, 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 de "bombilla" para mí: piense en las interfaces menos desde la perspectiva del autor y más en cualquier codificador que venga más adelante en la cadena y que esté agregando la implementación a un proyecto, o ampliando una API.



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.


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

Puedo proporcionar un puntero: 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?)


La regla básica es: para "Nombres" use la clase abstracta y para "Verbos" use la interfaz

Por ejemplo: el car es una clase abstracta y una drive , podemos convertirlo en una interfaz.


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 han sido implementados. Por lo tanto, puede garantizar una cierta cantidad de funcionalidad idéntica con una clase abstracta, pero no con una interfaz.

Aquí hay algunas recomendaciones para ayudarlo a decidir si usar una interfaz o una clase abstracta para proporcionar polimorfismo para 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 más adecuadas para proporcionar una funcionalidad común a las 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 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


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. Así que las interfaces te dan más flexibilidad. Pero esto no es cierto en C ++.


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 hereditaria debe implementar.

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

Ejemplo (¡uno muy rudimentario!): Considere una clase base llamada Cliente que tiene métodos abstractos como CalculatePayment() , CalculateRewardPoints() y algunos métodos no abstractos como GetName() , SavePaymentDetails() .

Las clases especializadas como RegularCustomer y GoldCustomer heredarán de la clase base del Customer e implementarán su propia lógica de método CalculatePayment() y CalculateRewardPoints() , pero reutilizarán los GetName() y SavePaymentDetails() .

Puede agregar más funcionalidad a una clase abstracta (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 recién agregados.

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


Para mí, me gustaría ir con interfaces en muchos casos. Pero prefiero 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, de lo contrario 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.


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

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

El problema con el "método de plantilla" es que casi siempre es un poco reingresivo: 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.

(Muy simplificado) ejemplo:

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" al proporcionar sus propios "ganchos"; en este caso, un método de "comparación".

Así que el uso previsto es algo como esto:

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

El problema con esto es que has juntado indebidamente dos conceptos:

  1. Una forma de comparar dos elementos (qué elemento debe ir primero)
  2. Un método de clasificación de elementos (es decir, quicksort vs combinación de clasificación, etc.)

En el código anterior, en teoría, el autor del método de "comparación" puede volver a llamar nuevamente al método de "clasificación" 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 idiomas OO, 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; } }

Notémoslo ahora: todo lo que tenemos son interfaces e implementaciones concretas de esas interfaces. En la práctica, realmente no necesita 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()); }

Siempre que tenga una clase abstracta, puede hacer esto ... incluso cuando existe una relación natural de reingreso entre la clase base y la clase derivada, por lo general vale la pena hacerlos explícitos.

Una última reflexión: todo lo que hemos hecho anteriormente es "componer" una función "NameSorting" usando una función "QuickSort" y una función "NameComparison" ... en un lenguaje de programación funcional, este estilo de programación se vuelve aún más natural. Con menos código.


Si usted está buscando en java como lenguaje OOP,

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

En términos simples, me gustaría usar

interfaz: para implementar un contrato por múltiples objetos no relacionados. Proporciona capacidad " HAS A ".

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

El website Oracle proporciona diferencias clave entre la interface y abstract clase abstract .

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.

Ejemplo:

Clase abstracta ( es una relación)

Reader es una clase abstracta.

BufferedReader es un Reader

FileReader es un Reader

FileReader y BufferedReader se usan para propósitos comunes: leer datos y están relacionados a través de la clase Reader .

Interfaz (tiene una capacidad)

Serializable es una interfaz.

Suponga que tiene dos clases en su aplicación, que están implementando una interfaz Serializable

Employee implements Serializable

Game implements Serializable

Aquí no puede establecer ninguna relación a través de la interfaz Serializable entre Employee y Game , que tienen un propósito diferente. Ambos son capaces de serializar el estado y la comparación termina ahí.

Echa un vistazo a estos mensajes:

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


Un lugar interesante donde las interfaces se desempeñan 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 básica (por ejemplo, están sealed o ya tienen un padre), puede darles una interfaz ficticia (vacía) y luego simplemente escribir los métodos de extensión para esa interfaz.


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


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 idioma: por ejemplo, C # no tiene herencia múltiple, pero se pueden implementar múltiples interfaces en una clase.


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


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


Solo en base a la herencia, usaría un Resumen en el que está definiendo claramente relaciones descendentes y abstractas (es decir, animal-> cat) y / o requeriría la herencia de propiedades virtuales o no públicas, especialmente el estado compartido (que Interfaces no puede admitir). ).

Debe probar y favorecer la composición (a través de la inyección de dependencia) sobre la herencia en la medida de lo posible, y tenga en cuenta que los Interfaces que son contratos respaldan la prueba de unidad, la separación de inquietudes y la herencia múltiple (en función del idioma) de una manera que los Resúmenes no pueden.


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

  1. Si se 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 red troncal para objetos que están estrechamente relacionados en una jerarquía, es altamente beneficioso usar una clase abstracta

¿Cuándo preferir una interfaz sobre clase abstracta?

  1. Si no se trata de un tipo de marco jerárquico masivo, las interfaces serían una excelente opción
  2. Debido a que la herencia múltiple no es compatible con clases abstractas (problema de diamante), las interfaces pueden salvar el día