Exploración del polimorfismo basado en herencia

Completado

El polimorfismo basado en herencia se basa en una jerarquía de clases donde las clases derivadas heredan el comportamiento y las propiedades de una clase base. La relación de herencia permite tratar objetos de clases derivadas como objetos de la clase base. La capacidad de tratar objetos de clase derivados como objetos de clase base permite escribir código que funcione con varios tipos de objetos sin conocer el tipo específico en tiempo de compilación.

En el ejemplo de código siguiente se muestra el polimorfismo basado en herencia en C#:


// Base class
public class Animal
{
    public virtual void MakeSound()
    {
        Console.WriteLine("The animal makes a sound.");
    }
}

// Derived class Dog
public class Dog : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("The dog barks.");
    }
}

// Derived class Cat
public class Cat : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("The cat meows.");
    }
}

// Derived class Cow
public class Cow : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("The cow moos.");
    }
}

class Program
{
    static void Main()
    {
        // Create an array of Animal objects
        Animal[] animals = new Animal[3];

        Animal animal1 = new Dog();
        Animal animal2 = new Cat();
        Animal animal3 = new Cow();

        animals[0] = animal1;
        animals[1] = animal2;
        animals[2] = animal3;

        // Demonstrate polymorphism
        foreach (Animal animal in animals)
        {
            animal.MakeSound();
        }
    }
}

En este código de ejemplo, observe que la clase Program crea una matriz de objetos Animal y asigna instancias de Dog, Cat y Cow a los elementos de matriz. Se llama al método MakeSound en cada objeto de la matriz, que muestra el polimorfismo. El método MakeSound se invalida en las clases derivadas para proporcionar un comportamiento específico para cada tipo animal.

Convertir un objeto de una clase base en una clase derivada

La conversión en C# es el proceso de convertir un objeto de un tipo a otro tipo. La conversión se usa a menudo al implementar polimorfismo mediante jerarquías de herencia, donde tiene una clase base y una o varias clases derivadas.

Hay dos tipos principales de conversión:

  • Conversión implícita: esto se produce automáticamente al convertir una clase derivada en una clase base. Es seguro porque cada instancia de una clase derivada también es una instancia de la clase base.

    
    BankAccount account = new CheckingAccount();
    
    
  • Conversión explícita: esto requiere un operador de conversión y se usa al convertir una clase base en una clase derivada. No siempre es seguro porque no todas las instancias de una clase base son una instancia de la clase derivada.

    
    CheckingAccount checkingAccount = (CheckingAccount)account;
    
    

Convertir objetos mediante las palabras clave is y as

En C#, puede convertir objetos usando las palabras clave is y as. Estas palabras clave proporcionan una manera segura de comprobar el tipo de un objeto antes de convertirlo a otro tipo. Estas son algunas formas comunes de convertir objetos en C#:

  • Uso de la palabra clave is con coincidencia de patrones:

    
    if (account is CheckingAccount checkingAccount)
    {
        // Use checkingAccount as a CheckingAccount
    }
    
    
    • Esta sintaxis comprueba si account es de tipo CheckingAccount.
    • Si la comprobación se realiza correctamente, convierte account en CheckingAccount y la asigna a la variable checkingAccount.
    • Este enfoque es conciso y seguro, ya que combina la comprobación de tipos y la conversión en un paso.
  • Con la palabra clave is seguida de la conversión explícita:

    
    if (account is CheckingAccount)
    {
        CheckingAccount checkingAccount = (CheckingAccount)account;
        // Use checkingAccount as a CheckingAccount
    }
    
    
    • Esta sintaxis comprueba si account es de tipo CheckingAccount.
    • Si la comprobación se realiza correctamente, convierte explícitamente account en CheckingAccount y la asigna a la variable checkingAccount.
    • Este enfoque es más detallado que la sintaxis de coincidencia de patrones, pero proporciona más control sobre el proceso de conversión.
  • Con la palabra clave as:

    
    CheckingAccount checkingAccount = account as CheckingAccount;
    
    if (checkingAccount != null)
    {
        // Use checkingAccount as a CheckingAccount
    }
    
    
    • Esta sintaxis intenta convertir account en CheckingAccount y asigna el resultado a checkingAccount.
    • Si la conversión es correcta, checkingAccount contiene el objeto de conversión; de lo contrario, es null.
    • Este enfoque es útil cuando desea comprobar el resultado de la conversión antes de usar el objeto de conversión. Por ejemplo, si desea evitar excepciones y controlar el caso de error correctamente.
  • Al implementar la conversión, tenga en cuenta las siguientes directrices:

    • Uso de la coincidencia de patrones con is: combina la comprobación de tipos y la conversión en un paso.
    • Uso de la palabra clave is con conversión explícita: separa la comprobación de tipos y convierte en dos pasos, lo que proporciona más control sobre el proceso de conversión.
    • Uso de la palabra clave as: los intentos de conversión y controlan el error correctamente devolviendo null.

Comprender estas técnicas de conversión es esencial para trabajar con polimorfismo y herencia en C#.

Evitar problemas comunes al implementar polimorfismo

Cuando el objetivo es el polimorfismo basado en herencia, estas son algunas cosas que se deben evitar y algunas cosas para garantizar:

  • Evite usar clases y métodos sellados: las clases y los métodos sellados no se pueden heredar ni invalidar, lo que limita la capacidad de usar polimorfismo. Si sella una clase o un método, se evita una mayor extensión y personalización. Por ejemplo:

    
    public sealed class BankAccount { } // This class can't be inherited
    
    
  • Evite el uso excesivo de métodos estáticos. Los métodos estáticos pertenecen a la propia clase en lugar de a una instancia de la clase. No se pueden invalidar, lo que significa que no participan en el polimorfismo.

    
    public static void PrintMessage() { } // This method can't be overridden
    
    
  • Evite emparejamiento estricto. El acoplamiento estricto se produce cuando las clases o componentes de un sistema dependen en gran medida entre sí. Esto significa que los cambios de una clase pueden afectar directamente a otras clases, lo que hace que el sistema sea menos flexible y más difícil de mantener. El acoplamiento estricto puede provocar dificultades en las pruebas, la extensión y la modificación del código.

    
    public class BankAccount
    {
        public void TransferFunds(SavingsAccount savingsAccount)
        {
            // Tight coupling with SavingsAccount
        }
    }
    
    
  • Evite usar la palabra clave "new" sin una buena razón. La palabra clave "new" oculta el método de clase base en la clase derivada, lo que puede provocar confusión y comportamiento inesperado. Use solo la palabra clave 'new' cuando quiera ocultar el método de clase base intencionadamente.

    
    public class Dog : Animal
    {
        public new void MakeSound() // Hides the base class method. Better to use 'override'
        {
            Console.WriteLine("The dog barks.");
        }
    }
    
    
  • Asegúrese de que las firmas de método sean coherentes. Asegúrese de que los métodos invalidados en las clases derivadas tengan la misma firma que el método de clase base. Si se cambia la firma del método, se ocultará el método en lugar de invalidarla.

    
    public class Animal
    {
        public virtual void MakeSound(string sound)
        {
            Console.WriteLine("The animal makes a sound.");
        }
    }
    
    public class Dog : Animal
    {
        // Method signature doesn't match the base class
        public override void MakeSound()
        {
            Console.WriteLine("The dog barks.");
        }
    }
    
    

Resumen

El polimorfismo basado en herencia en C# permite crear una jerarquía de clases donde las clases derivadas heredan el comportamiento y las propiedades de una clase base. Este mecanismo de herencia permite tratar objetos de clases derivadas como objetos de la clase base. La capacidad de tratar objetos de clase derivadas como miembros de una clase base permite escribir código que funcione con varios tipos de objetos sin conocer el tipo específico en tiempo de compilación. Al comprender las técnicas de conversión, evitar los problemas comunes y seguir los procedimientos recomendados, puede implementar de forma eficaz el polimorfismo en las aplicaciones de C#.