Programación Orientada a Objetos en C#

Programación Orientada a Objetos en C#

Compartir

En este capítulo, nos adentraremos en el emocionante mundo de la Programación Orientada a Objetos (POO) y exploraremos cómo se aplica en el lenguaje de programación C#. La POO es un paradigma fundamental en el desarrollo de software moderno y ofrece una forma poderosa y eficiente de diseñar y organizar programas. En este capítulo, presentaremos los conceptos clave de la POO y discutiremos su importancia en el desarrollo de software. También destacaremos cómo C# es un lenguaje orientado a objetos de primera clase que facilita la implementación de conceptos de POO.

Conceptos Clave de la Programación Orientada a Objetos (POO):

La Programación Orientada a Objetos es un paradigma de programación que se basa en el concepto de «objetos». Estos objetos son representaciones de entidades del mundo real que tienen propiedades y comportamientos. Los conceptos clave de la POO incluyen:

  1. Clases y Objetos: Las clases son plantillas que definen las propiedades y métodos de los objetos. Los objetos son instancias concretas de una clase.
  2. Encapsulamiento: El encapsulamiento es el principio de ocultar los detalles internos de una clase y exponer solo lo necesario. Proporciona seguridad y control sobre los datos y el comportamiento de un objeto.
  3. Herencia: La herencia permite que una clase herede propiedades y métodos de otra clase. Esto fomenta la reutilización de código y la creación de jerarquías de clases.
  4. Polimorfismo: El polimorfismo permite que objetos de diferentes clases respondan de manera diferente a la misma acción. Facilita la extensibilidad y flexibilidad del código.
  5. Métodos: Los métodos son funciones que están asociadas a una clase y definen el comportamiento de los objetos de esa clase. Los métodos pueden realizar acciones y manipular las propiedades de los objetos. Por ejemplo, un método «arrancar» de la clase «Coche» podría cambiar el estado del coche a «en marcha».
  6. Propiedades: Las propiedades son características o atributos de un objeto que almacenan datos. Pueden ser de diferentes tipos, como números, cadenas de texto, booleanos, etc. Por ejemplo, la propiedad «color» de un objeto «Coche» podría almacenar el color del coche.

Importancia de la POO en el Desarrollo de Software Moderno:

La POO ha revolucionado la forma en que desarrollamos software. Algunas de sus ventajas clave incluyen:

  • Reutilización de Código: La herencia y la creación de clases base permiten la reutilización de código, lo que reduce la duplicación y facilita el mantenimiento.
  • Modelado del Mundo Real: La POO permite modelar sistemas y procesos del mundo real de manera más natural, lo que facilita la comprensión y el diseño de software.
  • Flexibilidad y Escalabilidad: Los conceptos de POO como la encapsulación y el polimorfismo permiten que el código sea más flexible y escalable, lo que facilita la adaptación a cambios futuros.
  • Colaboración en Equipo: La POO fomenta la división del trabajo en equipos de desarrollo y la gestión de componentes individuales como objetos.
  • Mantenimiento Simplificado: El código orientado a objetos tiende a ser más fácil de mantener y depurar debido a su estructura organizada.

En este capítulo, exploraremos estos conceptos y más, y aprenderemos cómo aplicarlos en C# para diseñar y desarrollar software de manera efectiva y eficiente.

Clases y Objetos en C#

En C#, las clases y los objetos son elementos esenciales de la Programación Orientada a Objetos (POO). A continuación, exploraremos en detalle cómo definir y utilizar clases y objetos en C#:

Definición y Creación de Clases en C#:

Una clase en C# es una plantilla o un molde que define la estructura y el comportamiento de los objetos. Las clases se utilizan para representar entidades del mundo real en un programa. Aquí tienes un ejemplo simple de cómo se define una clase en C#:

public class Coche
{
    // Propiedades de la clase
    public string Marca { get; set; }
    public string Modelo { get; set; }
    
    // Constructor de la clase
    public Coche(string marca, string modelo)
    {
        Marca = marca;
        Modelo = modelo;
    }
    
    // Método de la clase
    public void Arrancar()
    {
        Console.WriteLine("El coche {0} {1} está en marcha.", Marca, Modelo);
    }
}

En el ejemplo anterior, hemos definido una clase llamada Coche que tiene propiedades como Marca y Modelo, un constructor que permite inicializar estas propiedades y un método llamado Arrancar que muestra un mensaje.

Creación de Objetos a partir de Clases:

Una vez que hemos definido una clase, podemos crear objetos a partir de ella. Los objetos son instancias concretas de una clase y se crean utilizando el operador new. Por ejemplo: Coche miCoche = new Coche(«Toyota», «Camry»); 

Hemos creado un objeto miCoche de la clase Coche y hemos proporcionado valores para las propiedades Marca y Modelo mediante el constructor.

Propiedades y Métodos de Clase:

Las propiedades son características o atributos de un objeto, mientras que los métodos son funciones que definen el comportamiento de un objeto. En el ejemplo de la clase Coche, las propiedades son Marca y Modelo, y el método es Arrancar. Puedes acceder a las propiedades y métodos de un objeto de la siguiente manera:

// Acceder a propiedades
string marcaDelCoche = miCoche.Marca;
string modeloDelCoche = miCoche.Modelo;

// Llamar a métodos
miCoche.Arrancar();

En este ejemplo, estamos accediendo a las propiedades Marca y Modelo del objeto miCoche y llamando al método Arrancar para iniciar el coche.

Las clases y objetos son fundamentales en la POO y permiten organizar y estructurar el código de manera efectiva al modelar entidades del mundo real en programas C#. En los capítulos siguientes, exploraremos más conceptos de POO y cómo trabajar con ellos en C#.

Herencia en C#

La herencia es un concepto fundamental en la Programación Orientada a Objetos (POO) que permite la creación de clases derivadas o subclases a partir de una clase base o superclase. En C#, la herencia se implementa utilizando la palabra clave :, y esto permite que las clases derivadas hereden propiedades y métodos de la clase base. A continuación, se detallan los conceptos clave relacionados con la herencia en C#:

Explicación de la Herencia:

La herencia es un mecanismo que permite la creación de una nueva clase (clase derivada) basada en una clase existente (clase base). La clase derivada hereda las propiedades y métodos de la clase base, lo que fomenta la reutilización de código y la creación de una jerarquía de clases. La clase derivada puede agregar nuevas propiedades y métodos o modificar el comportamiento heredado.

Creación de Clases Derivadas en C#:

Para crear una clase derivada en C#, se utiliza la siguiente sintaxis:

class ClaseDerivada : ClaseBase
{
    // Propiedades y métodos adicionales de la clase derivada
}

Donde ClaseDerivada es la nueva clase que estamos creando, y ClaseBase es la clase de la cual queremos heredar. La clase derivada heredará todas las propiedades y métodos públicos o protegidos de la clase base.

Uso de la Palabra Clave «base» y «override»:

En C#, la palabra clave base se utiliza para acceder a miembros de la clase base desde la clase derivada. Por ejemplo, si deseamos llamar a un constructor de la clase base desde la clase derivada, podemos hacerlo de la siguiente manera:

public class ClaseBase
{
    public ClaseBase(int valor)
    {
        // Constructor de la clase base
    }
}

public class ClaseDerivada : ClaseBase
{
    public ClaseDerivada(int valor) : base(valor)
    {
        // Constructor de la clase derivada
    }
}

La palabra clave override se utiliza para indicar que un método en la clase derivada reemplaza un método con el mismo nombre en la clase base. Esto se conoce como «sobreescritura de métodos». La firma del método en la clase derivada debe coincidir con la firma del método en la clase base.

public class ClaseBase
{
    public virtual void Metodo()
    {
        Console.WriteLine("Método de la clase base");
    }
}

public class ClaseDerivada : ClaseBase
{
    public override void Metodo()
    {
        Console.WriteLine("Método de la clase derivada");
    }
}

En este ejemplo, hemos sobreescrito el método Metodo en la clase derivada, y cuando se llama a Metodo en una instancia de la clase derivada, se ejecuta el código de la clase derivada en lugar del código de la clase base.

Ejemplo: Herencia en Acción – Clases «Vehículo» y «Coche»

Vamos a crear un ejemplo práctico para ilustrar cómo funciona la herencia en C# utilizando las clases «Vehículo» y «Coche». La clase «Vehículo» será la clase base, y la clase «Coche» será la clase derivada que hereda de «Vehículo». Comencemos:

using System;

// Clase base: Vehículo
class Vehiculo
{
    // Propiedades de la clase base
    public string Marca { get; set; }
    public string Modelo { get; set; }

    // Constructor de la clase base
    public Vehiculo(string marca, string modelo)
    {
        Marca = marca;
        Modelo = modelo;
    }

    // Método de la clase base
    public void Arrancar()
    {
        Console.WriteLine("El vehículo {0} {1} está en marcha.", Marca, Modelo);
    }
}

// Clase derivada: Coche
class Coche : Vehiculo
{
    // Propiedades adicionales de la clase derivada
    public int Año { get; set; }

    // Constructor de la clase derivada
    public Coche(string marca, string modelo, int año) : base(marca, modelo)
    {
        Año = año;
    }

    // Método adicional de la clase derivada
    public void Acelerar()
    {
        Console.WriteLine("El coche {0} {1} ({2}) está acelerando.", Marca, Modelo, Año);
    }
}

class Program
{
    static void Main()
    {
        // Crear un objeto de la clase derivada "Coche"
        Coche miCoche = new Coche("Toyota", "Camry", 2022);

        // Acceder a propiedades y métodos heredados de la clase base "Vehículo"
        miCoche.Arrancar(); // Método heredado de la clase base
        Console.WriteLine("Marca: {0}, Modelo: {1}, Año: {2}", miCoche.Marca, miCoche.Modelo, miCoche.Año);

        // Llamar al método adicional de la clase derivada "Coche"
        miCoche.Acelerar();

        // Salida:
        // El vehículo Toyota Camry está en marcha.
        // Marca: Toyota, Modelo: Camry, Año: 2022
        // El coche Toyota Camry (2022) está acelerando.
    }
}

En este ejemplo, hemos creado una clase base llamada «Vehículo» con propiedades y un método. Luego, creamos una clase derivada llamada «Coche» que hereda de «Vehículo» y agrega una propiedad y un método adicionales.

En el método Main, creamos un objeto de la clase derivada «Coche» y demostramos cómo se pueden acceder a las propiedades y métodos tanto de la clase base como de la clase derivada. Esto ilustra cómo la herencia permite compartir atributos y comportamientos entre clases relacionadas en C#.

Encapsulamiento en C#

El encapsulamiento es uno de los conceptos clave en la Programación Orientada a Objetos (POO) y se refiere a la práctica de ocultar los detalles internos de una clase y proporcionar una interfaz pública para interactuar con ella. En C#, el encapsulamiento se logra mediante el uso de modificadores de acceso, como public, private, protected, e internal, para controlar la visibilidad y accesibilidad de los miembros de una clase, como propiedades y métodos. Aquí hay una explicación detallada del encapsulamiento en C#:

Definición del Encapsulamiento:

El encapsulamiento consiste en ocultar los detalles internos de una clase y proporcionar una interfaz pública clara y controlada para interactuar con la clase. Esto se hace para proteger los datos y el comportamiento de la clase, evitando que se modifiquen de manera incorrecta desde fuera de la clase.

Modificadores de Acceso:

En C#, existen cuatro modificadores de acceso principales que se utilizan para controlar la visibilidad de los miembros de una clase:

  • public: Los miembros marcados como public son accesibles desde cualquier parte del programa, incluso desde fuera de la clase.
  • private: Los miembros marcados como private solo son accesibles desde dentro de la misma clase.
  • protected: Los miembros marcados como protected son accesibles desde la misma clase y sus clases derivadas.
  • internal: Los miembros marcados como internal son accesibles desde cualquier clase dentro del mismo ensamblado (assembly).

Propiedades y Métodos Encapsulados:

Para aplicar el encapsulamiento en C#, se suelen utilizar propiedades y métodos encapsulados. Las propiedades encapsuladas permiten controlar el acceso a los campos privados de una clase, mientras que los métodos encapsulados permiten realizar operaciones controladas en esos campos.

Aquí tienes un ejemplo de cómo se utiliza el encapsulamiento en C# con propiedades encapsuladas:

public class Persona
{
    // Campo privado
    private string nombre;

    // Propiedad encapsulada
    public string Nombre
    {
        get { return nombre; }
        set { nombre = value; }
    }
}

En este ejemplo, el campo nombre está encapsulado dentro de la propiedad Nombre. Esto permite que el valor del campo solo sea accesible y modificable a través de la propiedad, lo que proporciona un mayor control sobre los datos.

El encapsulamiento es fundamental para mantener la integridad de los datos y el comportamiento de una clase en C#. Al ocultar los detalles internos, una clase puede evolucionar sin afectar a otras partes del programa que la utilizan, lo que facilita el mantenimiento y la expansión del código.

Ejemplo: Encapsulamiento en la Clase «Cuenta Bancaria»

Vamos a crear un ejemplo de una clase «Cuenta Bancaria» que demuestra el uso de encapsulamiento en C#. Esta clase tendrá atributos encapsulados y métodos para depositar y retirar dinero de la cuenta. Aquí está el código:

using System;

public class CuentaBancaria
{
    private string titular;
    private double saldo;

    // Constructor
    public CuentaBancaria(string titular)
    {
        this.titular = titular;
        saldo = 0.0;
    }

    // Propiedad encapsulada para el saldo
    public double Saldo
    {
        get { return saldo; }
    }

    // Método para depositar dinero en la cuenta
    public void Depositar(double cantidad)
    {
        if (cantidad > 0)
        {
            saldo += cantidad;
            Console.WriteLine("Depósito de {0} realizado. Saldo actual: {1:C}", cantidad, saldo);
        }
        else
        {
            Console.WriteLine("El monto del depósito debe ser mayor que cero.");
        }
    }

    // Método para retirar dinero de la cuenta
    public void Retirar(double cantidad)
    {
        if (cantidad > 0 && cantidad <= saldo)
        {
            saldo -= cantidad;
            Console.WriteLine("Retiro de {0} realizado. Saldo actual: {1:C}", cantidad, saldo);
        }
        else
        {
            Console.WriteLine("Monto de retiro no válido o insuficiente saldo.");
        }
    }
}

class Program
{
    static void Main()
    {
        // Crear una cuenta bancaria
        CuentaBancaria cuenta = new CuentaBancaria("Juan Pérez");

        // Realizar operaciones
        cuenta.Depositar(1000.0);
        cuenta.Retirar(500.0);
        cuenta.Retirar(700.0);

        // Consultar saldo
        Console.WriteLine("Saldo final de la cuenta de {0}: {1:C}", cuenta.Saldo, cuenta.Saldo);
    }
}

En este ejemplo, hemos encapsulado los atributos titular y saldo dentro de la clase «Cuenta Bancaria». La propiedad Saldo permite obtener el saldo actual de la cuenta, pero no permite modificarlo directamente. Los métodos Depositar y Retirar proporcionan una forma controlada de realizar operaciones en la cuenta, verificando que las cantidades sean válidas y que haya suficiente saldo.

Este ejemplo ilustra cómo el encapsulamiento permite controlar el acceso a los datos y el comportamiento de la clase, proporcionando un alto grado de seguridad y coherencia en la manipulación de objetos.

Polimorfismo en C#

El polimorfismo es uno de los principios fundamentales de la Programación Orientada a Objetos (POO) que permite que objetos de diferentes clases puedan ser tratados de manera uniforme. En C#, el polimorfismo se puede lograr de varias maneras, incluyendo la implementación de interfaces y el uso de clases abstractas. Aquí tienes una explicación detallada del polimorfismo y sus tipos:

Explicación del Polimorfismo:

El polimorfismo es un principio de la POO que permite que objetos de diferentes clases puedan ser tratados de manera uniforme a través de una interfaz común. Esto significa que un objeto puede tomar diferentes formas o comportamientos según el contexto en el que se utilice. El polimorfismo se basa en dos conceptos clave:

  1. Polimorfismo Estático (Compile-time Polymorphism): También conocido como enlace temprano, ocurre en tiempo de compilación. Se relaciona con la sobrecarga de métodos y operadores, donde una clase tiene múltiples métodos con el mismo nombre pero diferentes parámetros.
  2. Polimorfismo Dinámico (Run-time Polymorphism): También conocido como enlace tardío, ocurre en tiempo de ejecución. Se relaciona con la implementación de métodos virtuales y la anulación (override) de métodos en clases derivadas. Permite que un objeto de una clase derivada se comporte como un objeto de su clase base.

Implementación de Polimorfismo en C#:

  1. Polimorfismo Estático:

Sobrecarga de Métodos: En C#, puedes definir varios métodos con el mismo nombre en una clase, pero con diferentes parámetros. El compilador seleccionará el método apropiado en función de la lista de argumentos utilizada en la llamada.

public class Calculadora
{
    public int Sumar(int a, int b)
    {
        return a + b;
    }

    public double Sumar(double a, double b)
    {
        return a + b;
    }
}
  1. Polimorfismo Dinámico:

Métodos Virtuales y Anulación (Override): En C#, puedes declarar un método como virtual en una clase base y luego anularlo en clases derivadas utilizando la palabra clave override. Esto permite que un objeto de la clase derivada se comporte de manera específica, incluso cuando se llama a través de una referencia de la clase base.

public class Figura
{
    public virtual void Dibujar()
    {
        Console.WriteLine("Dibujando una figura genérica");
    }
}

public class Circulo : Figura
{
    public override void Dibujar()
    {
        Console.WriteLine("Dibujando un círculo");
    }
}

  1. Interfaces y Polimorfismo:

Las interfaces en C# permiten definir un contrato común que las clases pueden implementar. Puedes utilizar interfaces para lograr el polimorfismo, ya que varios objetos de diferentes clases pueden implementar la misma interfaz y ser tratados de manera uniforme a través de esa interfaz.

public interface IDibujable
{
    void Dibujar();
}

public class Circulo : IDibujable
{
    public void Dibujar()
    {
        Console.WriteLine("Dibujando un círculo");
    }
}

public class Cuadrado : IDibujable
{
    public void Dibujar()
    {
        Console.WriteLine("Dibujando un cuadrado");
    }
}

El polimorfismo es fundamental en la POO, ya que permite escribir código más genérico y reutilizable al tratar objetos de manera uniforme a través de interfaces comunes y al permitir que las clases derivadas definan su propio comportamiento.

Ejemplo: Interfaces y Polimorfismo en Figuras Geométricas

En este ejemplo, crearemos una interfaz llamada IFigura que define un método para calcular el área de una figura geométrica. Luego, implementaremos esta interfaz en varias clases que representan diferentes figuras geométricas, como círculos y rectángulos. Utilizaremos el polimorfismo para calcular el área de estas figuras de manera uniforme a través de la interfaz común.

using System;

// Definición de la interfaz IFigura que incluye un método para calcular el área.
public interface IFigura
{
    double CalcularArea();
}

// Implementación de la interfaz IFigura para un círculo.
public class Circulo : IFigura
{
    public double Radio { get; set; }

    public Circulo(double radio)
    {
        Radio = radio;
    }

    public double CalcularArea()
    {
        return Math.PI * Math.Pow(Radio, 2);
    }
}

// Implementación de la interfaz IFigura para un rectángulo.
public class Rectangulo : IFigura
{
    public double Largo { get; set; }
    public double Ancho { get; set; }

    public Rectangulo(double largo, double ancho)
    {
        Largo = largo;
        Ancho = ancho;
    }

    public double CalcularArea()
    {
        return Largo * Ancho;
    }
}

public class Program
{
    public static void Main()
    {
        // Creación de instancias de figuras geométricas.
        IFigura circulo = new Circulo(5.0);
        IFigura rectangulo = new Rectangulo(4.0, 6.0);

        // Cálculo de áreas utilizando polimorfismo.
        double areaCirculo = circulo.CalcularArea();
        double areaRectangulo = rectangulo.CalcularArea();

        // Mostrar resultados.
        Console.WriteLine($"Área del círculo: {areaCirculo}");
        Console.WriteLine($"Área del rectángulo: {areaRectangulo}");
    }
}

En este ejemplo, creamos una interfaz IFigura que incluye el método CalcularArea(). Luego, implementamos esta interfaz en las clases Circulo y Rectangulo. Utilizamos el polimorfismo para calcular el área de estas figuras de manera uniforme a través de la interfaz común, lo que facilita el cálculo de áreas sin importar el tipo de figura geométrica.

Resumen:

En este capítulo, exploramos los fundamentos de la Programación Orientada a Objetos (POO) en el contexto del lenguaje de programación C#. Aquí están los puntos clave que hemos cubierto:

  1. Conceptos de POO (Programación Orientada a Objetos): Explicamos en detalle los conceptos fundamentales de la POO, incluyendo objetos, clases, métodos, propiedades, herencia, encapsulamiento y polimorfismo. Destacamos las ventajas de la POO en el diseño de software
  2. Clases y Objetos en C#: Definimos y creamos clases en C#. Mostramos cómo crear objetos a partir de clases y cómo trabajar con propiedades y métodos de clase.
  3. Herencia en C#: Explicamos la herencia como un concepto fundamental de la POO. Demostramos la creación de clases derivadas y base en C#, así como el uso de las palabras clave «base» y «override».
  4. Ejemplo: Herencia en Acción: Clases «Vehículo» y «Coche»: Creamos una clase base «Vehículo» y una clase derivada «Coche» para mostrar cómo la herencia permite compartir atributos y comportamientos.
  5. Encapsulamiento en C#: Definimos el encapsulamiento y su importancia en la POO. Explicamos el uso de modificadores de acceso como public, private, protected e internal, así como propiedades y métodos encapsulados.
  6. Polimorfismo en C#: Explicamos el polimorfismo y sus tipos, estático y dinámico. Implementamos polimorfismo utilizando interfaces y clases abstractas.

Este capítulo sienta las bases para comprender la POO en C# y cómo utilizarla para diseñar aplicaciones eficientes y flexibles. Los conceptos de herencia, encapsulamiento y polimorfismo son fundamentales para crear software escalable y mantenible en C#. En el próximo capítulo, exploraremos aún más los conceptos avanzados de C# y su aplicación en el desarrollo de software práctico.

Ejemplo: Creación de una Jerarquía de Clases de Animales en C#

En este ejercicio, crearemos una jerarquía de clases que representan diferentes tipos de animales utilizando herencia y polimorfismo en C#. El objetivo es modelar diferentes comportamientos de estos animales en un programa simple. Aquí está el paso a paso:

Paso 1: Definir la Clase Base «Animal»

public class Animal
{
    public string Nombre { get; set; }
    public int Edad { get; set; }

    public virtual void HacerSonido()
    {
        Console.WriteLine("El animal hace un sonido.");
    }
}

En este paso, hemos creado una clase base llamada «Animal» que tiene propiedades comunes como Nombre y Edad. También hemos definido un método virtual llamado «HacerSonido» que imprimirá un mensaje genérico.

Paso 2: Crear Clases Derivadas para Tipos de Animales Específicos

public class Perro : Animal
{
    public override void HacerSonido()
    {
        Console.WriteLine("El perro ladra.");
    }
}

public class Gato : Animal
{
    public override void HacerSonido()
    {
        Console.WriteLine("El gato maulla.");
    }
}

public class Pajaro : Animal
{
    public override void HacerSonido()
    {
        Console.WriteLine("El pájaro canta.");
    }
}

En este paso, hemos creado clases derivadas para representar tipos de animales específicos como «Perro,» «Gato» y «Pájaro.» Cada una de estas clases hereda de la clase base «Animal» y proporciona su propia implementación del método «HacerSonido.»

Paso 3: Crear Instancias de Animales y Usar Polimorfismo

class Program
{
    static void Main(string[] args)
    {
        Animal miAnimal = new Perro();
        miAnimal.Nombre = "Max";
        miAnimal.Edad = 3;

        Animal otroAnimal = new Gato();
        otroAnimal.Nombre = "Whiskers";
        otroAnimal.Edad = 2;

        Animal tercerAnimal = new Pajaro();
        tercerAnimal.Nombre = "Tweetie";
        tercerAnimal.Edad = 1;

        Console.WriteLine($"Nombre: {miAnimal.Nombre}, Edad: {miAnimal.Edad}");
        miAnimal.HacerSonido();

        Console.WriteLine($"Nombre: {otroAnimal.Nombre}, Edad: {otroAnimal.Edad}");
        otroAnimal.HacerSonido();

        Console.WriteLine($"Nombre: {tercerAnimal.Nombre}, Edad: {tercerAnimal.Edad}");
        tercerAnimal.HacerSonido();
    }
}

En el método Main, hemos creado instancias de diferentes tipos de animales y las hemos inicializado con valores de nombre y edad. Luego, hemos llamado al método «HacerSonido» de cada animal, y gracias al polimorfismo, cada animal emite su propio sonido específico.

Este ejercicio demuestra cómo utilizar herencia y polimorfismo en C# para modelar diferentes comportamientos en una jerarquía de clases. Puedes expandir esta jerarquía agregando más clases de animales y comportamientos según sea necesario.


Compartir

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *