Menu
CoddyTech

Interfaz vs. Clase Abstracta

Parte de la sección Programación Orientada a Objetos del Journey de C# de Coddy. Lección 26 de 70.

Tanto las interfaces como las clases abstractas te permiten definir contratos que otras clases deben cumplir, pero tienen propósitos distintos y capacidades diferentes.

Una interfaz define lo que debe hacer una clase, sin ninguna implementación. Es un contrato puro:

public interface IFlyable
{
    void Fly();
}

public class Bird : IFlyable
{
    public void Fly()
    {
        Console.WriteLine("Flapping wings");
    }
}

Una clase abstracta puede proporcionar tanto un contrato como una implementación compartida. Es un plano parcial:

public abstract class Vehicle
{
    public string Brand { get; set; }
    
    public void StartEngine()
    {
        Console.WriteLine("Engine started");
    }
    
    public abstract void Drive();  // Debe implementarse
}

public class Car : Vehicle
{
    public override void Drive()
    {
        Console.WriteLine("Driving on roads");
    }
}

Las diferencias clave se reducen a las reglas de herencia y al propósito.

Una clase puede implementar varias interfaces, pero heredar de una sola clase abstracta.

Una clase también puede heredar de una clase abstracta e implementar interfaces al mismo tiempo: después de los dos puntos, va primero la clase base y luego las interfaces, separadas por comas:

public class Airplane : Vehicle, IFlyable
{
    public override void Drive()
    {
        Console.WriteLine("Taxiing to the runway");
    }

    public void Fly()
    {
        Console.WriteLine("Flying above the clouds");
    }
}

Usa una interfaz cuando clases no relacionadas necesiten compartir comportamiento (como IFlyable para aves y aviones). Usa una clase abstracta cuando clases relacionadas compartan código y estado comunes (como los vehículos que comparten un mecanismo de arranque del motor).

Las clases abstractas pueden tener constructores, campos y modificadores de acceso en sus miembros. Tradicionalmente, las interfaces no podían tenerlos, aunque las versiones modernas de C# permiten implementaciones predeterminadas.

En caso de duda, prefiere las interfaces por su flexibilidad: siempre puedes añadir una clase abstracta más adelante si se necesita una implementación compartida.

challenge icon

Desafío

Fácil

Vamos a crear un sistema de reproducción multimedia que muestre cuándo usar interfaces en lugar de clases abstractas. Diseñarás un sistema en el que dispositivos no relacionados compartan el comportamiento de reproducción mediante una interfaz, mientras que tipos de medios relacionados compartan una implementación común mediante una clase abstracta.

Organizarás el código en cuatro archivos:

  • IPlayable.cs: Define una interfaz llamada IPlayable en el espacio de nombres Media. Esta interfaz representa el contrato de cualquier elemento que pueda reproducir medios, ya sea un teléfono, un televisor o un reproductor de música dedicado. Debe declarar un único método Play() que devuelva una cadena.
  • MediaFile.cs: Define una clase abstracta llamada MediaFile en el espacio de nombres Media. Esta representa la base compartida de todos los archivos multimedia. Debe tener una propiedad Title (string) y una propiedad Duration (int, que representa los segundos). Incluye un constructor que establezca ambos valores. Añade un método concreto llamado GetInfo() que devuelva "{Title} ({Duration}s)". Declara también un método abstracto GetType() que devuelva una cadena; cada tipo de medio definirá qué clase de archivo es.
  • AudioFile.cs: Define una clase AudioFile en el espacio de nombres Media que herede de MediaFile e implemente IPlayable. Añade una propiedad Artist (string). El constructor debe aceptar el título, la duración y el artista. Sobrescribe GetType() para que devuelva "Audio". Implementa Play() para que devuelva "Playing audio: {Title} by {Artist}".
  • Program.cs: En el archivo principal, crea un AudioFile usando los valores de entrada. Muestra ambos aspectos de la clase: llama a GetInfo() y GetType() (heredados de la clase abstracta) y luego llama a Play() (de la interfaz). Guarda el archivo de audio en una variable IPlayable y vuelve a llamar a Play() para mostrar el polimorfismo de interfaz.

Recibirás tres entradas:

  • Título de la canción
  • Duración en segundos
  • Nombre del artista

Imprime la salida con este formato:

Info: {GetInfo() result}
Type: {GetType() result}
Direct: {Play() result}
Via Interface: {Play() result from IPlayable variable}

Por ejemplo, si las entradas son Bohemian Rhapsody, 354 y Queen, la salida debería ser:

Info: Bohemian Rhapsody (354s)
Type: Audio
Direct: Playing audio: Bohemian Rhapsody by Queen
Via Interface: Playing audio: Bohemian Rhapsody by Queen

Observa cómo AudioFile se beneficia de ambos enfoques: hereda una implementación compartida (GetInfo()) de la clase abstracta y, al mismo tiempo, cumple el contrato de IPlayable. La clase abstracta permite reutilizar código entre tipos de medios relacionados, mientras que la interfaz permite que cualquier clase no relacionada pueda ser «reproducible» sin compartir una jerarquía de herencia.

Pruébalo tú mismo

using System;
using Media;

class Program
{
    public static void Main(string[] args)
    {
        // Lee los valores de entrada
        string title = Console.ReadLine();
        int duration = Convert.ToInt32(Console.ReadLine());
        string artist = Console.ReadLine();
        
        // TODO: Crea un AudioFile usando los valores de entrada
        
        // TODO: Imprime Info: seguido del resultado de GetInfo()
        
        // TODO: Imprime Type: seguido del resultado de GetType()
        
        // TODO: Imprime Direct: seguido del resultado de Play()
        
        // TODO: Almacena el archivo de audio en una variable IPlayable
        
        // TODO: Imprime Via Interface: seguido del resultado de Play() de la variable IPlayable
    }
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de C# online