CSharp
Tutorial CSharp: Métodos virtuales y sobrecarga
Aprende en C# la diferencia entre métodos virtuales, sobrecarga y sobreescritura para dominar el polimorfismo y la programación orientada a objetos.
Aprende CSharp y certifícateSobrecarga vs sobreescritura
En la programación orientada a objetos con C#, existen dos conceptos fundamentales que a menudo se confunden: la sobrecarga y la sobreescritura de métodos. Aunque ambos permiten definir múltiples versiones de métodos, funcionan de manera completamente diferente y tienen propósitos distintos.
Sobrecarga de métodos
La sobrecarga de métodos permite definir múltiples métodos con el mismo nombre pero con diferentes parámetros dentro de la misma clase. El compilador determina qué versión del método invocar basándose en los argumentos proporcionados.
Características principales de la sobrecarga:
- Ocurre en la misma clase
- Los métodos tienen el mismo nombre
- Difieren en el número, tipo o orden de parámetros
- No tiene relación con la herencia
- No requiere palabras clave especiales
Veamos un ejemplo sencillo de sobrecarga:
public class Calculadora
{
// Sobrecarga para sumar dos enteros
public int Sumar(int a, int b)
{
return a + b;
}
// Sobrecarga para sumar tres enteros
public int Sumar(int a, int b, int c)
{
return a + b + c;
}
// Sobrecarga para sumar dos decimales
public double Sumar(double a, double b)
{
return a + b;
}
}
En este ejemplo, tenemos tres versiones del método Sumar
. El compilador seleccionará automáticamente la versión correcta según los argumentos que pasemos:
Calculadora calc = new Calculadora();
int resultado1 = calc.Sumar(5, 10); // Llama a Sumar(int, int)
int resultado2 = calc.Sumar(5, 10, 15); // Llama a Sumar(int, int, int)
double resultado3 = calc.Sumar(2.5, 3.5); // Llama a Sumar(double, double)
Sobreescritura de métodos
La sobreescritura permite a una clase derivada proporcionar una implementación específica de un método que ya está definido en su clase base. A diferencia de la sobrecarga, la sobreescritura:
- Ocurre entre clases relacionadas por herencia
- Los métodos tienen exactamente la misma firma (nombre y parámetros)
- Requiere que el método base esté marcado como
virtual
,abstract
ooverride
- La clase derivada usa la palabra clave
override
Veamos un ejemplo básico:
public class Animal
{
// Método virtual que puede ser sobreescrito
public virtual string HacerSonido()
{
return "...";
}
}
public class Perro : Animal
{
// Sobreescritura del método HacerSonido
public override string HacerSonido()
{
return "Guau";
}
}
public class Gato : Animal
{
// Otra sobreescritura del mismo método
public override string HacerSonido()
{
return "Miau";
}
}
En este ejemplo, cada clase derivada proporciona su propia implementación del método HacerSonido()
. Cuando llamamos al método, se ejecuta la versión correspondiente al tipo real del objeto:
Animal miAnimal = new Perro();
Console.WriteLine(miAnimal.HacerSonido()); // Imprime "Guau"
miAnimal = new Gato();
Console.WriteLine(miAnimal.HacerSonido()); // Imprime "Miau"
Diferencias clave entre sobrecarga y sobreescritura
Para entender mejor las diferencias, veamos una comparación directa:
Característica | Sobrecarga | Sobreescritura |
---|---|---|
Propósito | Proporcionar múltiples versiones de un método para diferentes tipos de parámetros | Modificar o extender el comportamiento de un método heredado |
Ubicación | Misma clase | Entre clase base y derivada |
Firma del método | Mismo nombre, diferentes parámetros | Exactamente la misma firma (nombre y parámetros) |
Tipo de retorno | Puede ser diferente | Debe ser el mismo o un tipo derivado (covarianza) |
Palabras clave | No requiere palabras clave especiales | Requiere virtual en la base y override en la derivada |
Resolución | En tiempo de compilación | En tiempo de ejecución (polimorfismo) |
Ejemplo combinado
Veamos un ejemplo que muestra tanto sobrecarga como sobreescritura:
public class Forma
{
// Método sobreescribible con una versión
public virtual double CalcularArea()
{
return 0;
}
// Método sobreescribible con otra versión (sobrecarga)
public virtual double CalcularArea(double factor)
{
return CalcularArea() * factor;
}
}
public class Circulo : Forma
{
private double radio;
public Circulo(double radio)
{
this.radio = radio;
}
// Sobreescritura del primer método
public override double CalcularArea()
{
return Math.PI * radio * radio;
}
// Sobreescritura del segundo método (sobrecargado)
public override double CalcularArea(double factor)
{
// Podemos llamar a la implementación base si queremos
return base.CalcularArea(factor);
// O podríamos hacer nuestra propia implementación:
// return Math.PI * radio * radio * factor;
}
// Agregamos otra sobrecarga (no sobreescritura)
public double CalcularArea(string unidad)
{
double area = CalcularArea();
return unidad.ToLower() == "cm" ? area : area * 100;
}
}
En este ejemplo:
- La clase
Forma
define dos versiones sobrecargadas del métodoCalcularArea
- La clase
Circulo
sobreescribe ambas versiones Circulo
también agrega una tercera versión sobrecargada que no existe en la clase base
Consideraciones importantes
- La sobrecarga es una técnica para proporcionar diferentes formas de invocar una operación similar con diferentes tipos o cantidades de datos.
- La sobreescritura es una característica del polimorfismo que permite a las clases derivadas proporcionar implementaciones específicas de métodos heredados.
- No se puede sobreescribir un método que no esté marcado como
virtual
,abstract
o ya seaoverride
. - Los métodos
sealed
no pueden ser sobreescritos en clases derivadas. - Los métodos
static
no pueden ser sobreescritos (aunque pueden ser ocultados connew
).
Entender la diferencia entre sobrecarga y sobreescritura es fundamental para aprovechar correctamente la flexibilidad que ofrece C# en el diseño orientado a objetos.
Métodos con virtual
En C#, la palabra clave virtual es fundamental para habilitar el polimorfismo en la programación orientada a objetos. Un método marcado como virtual indica que puede ser sobreescrito por clases derivadas, permitiendo diferentes implementaciones del mismo comportamiento según el tipo específico del objeto.
Declaración de métodos virtuales
Para declarar un método como virtual, simplemente se antepone la palabra clave virtual
a la declaración del método:
public class ClaseBase
{
public virtual void MiMetodo()
{
Console.WriteLine("Implementación en la clase base");
}
}
Cuando un método se declara como virtual
:
- Proporciona una implementación predeterminada que las clases derivadas pueden utilizar tal cual
- Permite a las clases derivadas modificar ese comportamiento mediante sobreescritura
- Mantiene la misma firma (nombre, parámetros y tipo de retorno) en toda la jerarquía
Características importantes de los métodos virtuales
Los métodos virtuales tienen varias características que es importante conocer:
- Solo pueden declararse en métodos de instancia (no en métodos estáticos)
- No pueden ser privados (pues no tendría sentido sobreescribir algo inaccesible)
- Deben tener una implementación (a diferencia de los métodos abstractos)
- La sobreescritura es opcional para las clases derivadas
Cuándo usar métodos virtuales
Los métodos virtuales son especialmente útiles cuando:
- Quieres proporcionar un comportamiento predeterminado que la mayoría de las clases derivadas pueden usar
- Necesitas permitir que algunas clases derivadas personalicen ese comportamiento
- Deseas trabajar con objetos a través de referencias de tipo base pero ejecutar la implementación más específica
Ejemplo práctico de métodos virtuales
Veamos un ejemplo que ilustra el uso de métodos virtuales en una jerarquía de clases:
public class Empleado
{
public string Nombre { get; set; }
public decimal SalarioBase { get; set; }
public Empleado(string nombre, decimal salarioBase)
{
Nombre = nombre;
SalarioBase = salarioBase;
}
// Método virtual con implementación predeterminada
public virtual decimal CalcularSalario()
{
return SalarioBase;
}
// Otro método virtual
public virtual string ObtenerDetalles()
{
return $"Empleado: {Nombre}, Salario: {CalcularSalario():C}";
}
}
En este ejemplo, la clase Empleado
define dos métodos virtuales: CalcularSalario()
y ObtenerDetalles()
. Ambos proporcionan una implementación predeterminada, pero pueden ser sobreescritos por clases derivadas.
Métodos virtuales vs métodos no virtuales
Para entender mejor la importancia de los métodos virtuales, comparemos el comportamiento de métodos virtuales y no virtuales:
public class Base
{
// Método no virtual
public void MetodoNormal()
{
Console.WriteLine("Base.MetodoNormal()");
}
// Método virtual
public virtual void MetodoVirtual()
{
Console.WriteLine("Base.MetodoVirtual()");
}
}
public class Derivada : Base
{
// Oculta el método no virtual (no recomendado)
public new void MetodoNormal()
{
Console.WriteLine("Derivada.MetodoNormal()");
}
// Sobreescribe el método virtual
public override void MetodoVirtual()
{
Console.WriteLine("Derivada.MetodoVirtual()");
}
}
Veamos cómo se comportan estos métodos:
Base b = new Base();
Derivada d = new Derivada();
Base bd = new Derivada(); // Referencia de tipo Base a objeto Derivada
// Llamadas a métodos no virtuales
b.MetodoNormal(); // Imprime: Base.MetodoNormal()
d.MetodoNormal(); // Imprime: Derivada.MetodoNormal()
bd.MetodoNormal(); // Imprime: Base.MetodoNormal() (¡Importante!)
// Llamadas a métodos virtuales
b.MetodoVirtual(); // Imprime: Base.MetodoVirtual()
d.MetodoVirtual(); // Imprime: Derivada.MetodoVirtual()
bd.MetodoVirtual(); // Imprime: Derivada.MetodoVirtual() (¡Importante!)
La diferencia clave está en la última línea de cada bloque. Con métodos no virtuales, el tipo de la referencia determina qué método se llama. Con métodos virtuales, el tipo del objeto real determina qué método se ejecuta, independientemente del tipo de la referencia.
Métodos virtuales y constructores
Es importante destacar que los constructores no pueden ser virtuales. Esto se debe a que los constructores no se heredan y siempre son específicos para cada clase. Sin embargo, se pueden llamar métodos virtuales desde los constructores, aunque esto requiere precaución:
public class Base
{
public Base()
{
// Llamada a método virtual desde el constructor
// ¡Precaución! Si una clase derivada sobreescribe este método,
// se llamará a la versión sobreescrita antes de que el constructor
// de la clase derivada se ejecute completamente
MetodoVirtual();
}
public virtual void MetodoVirtual()
{
Console.WriteLine("Base.MetodoVirtual()");
}
}
public class Derivada : Base
{
private string dato;
public Derivada()
{
// Este código se ejecuta después de que el constructor de Base haya terminado
dato = "Inicializado";
}
public override void MetodoVirtual()
{
// ¡Peligro! Este método podría ejecutarse antes de que 'dato' esté inicializado
Console.WriteLine($"Derivada.MetodoVirtual(), dato: {dato ?? "null"}");
}
}
Al crear una instancia de Derivada
, la salida sería:
Derivada.MetodoVirtual(), dato: null
Esto ocurre porque el constructor de la clase base se ejecuta antes que el constructor de la clase derivada, pero el método virtual ya está "vinculado" a la implementación de la clase derivada.
Rendimiento de los métodos virtuales
Los métodos virtuales tienen un pequeño impacto en el rendimiento debido a la resolución dinámica en tiempo de ejecución:
- Los métodos no virtuales se resuelven en tiempo de compilación (enlace temprano)
- Los métodos virtuales se resuelven en tiempo de ejecución (enlace tardío)
Este impacto es generalmente insignificante en aplicaciones modernas, pero puede ser relevante en código que se ejecuta millones de veces en bucles críticos para el rendimiento.
Métodos virtuales en interfaces (C# 8.0+)
A partir de C# 8.0, las interfaces pueden contener implementaciones predeterminadas de métodos, que funcionan de manera similar a los métodos virtuales:
public interface INotificador
{
// Método con implementación predeterminada
void Notificar(string mensaje)
{
Console.WriteLine($"Notificación estándar: {mensaje}");
}
}
public class NotificadorUrgente : INotificador
{
// Implementación personalizada
public void Notificar(string mensaje)
{
Console.WriteLine($"¡URGENTE! {mensaje}");
}
}
Aunque la sintaxis es diferente (no se usan las palabras clave virtual
y override
), el concepto es similar: proporcionar un comportamiento predeterminado que puede ser personalizado por las implementaciones.
Limitaciones de los métodos virtuales
Existen algunas limitaciones importantes al trabajar con métodos virtuales:
- No se pueden declarar como
static
,private
osealed
(aunque un métodooverride
puede sersealed
) - No se pueden cambiar los modificadores de acceso al sobreescribir (debe mantenerse la misma visibilidad)
- No se pueden cambiar los parámetros ni el tipo de retorno (excepto por covarianza)
Ejemplo completo de jerarquía con métodos virtuales
Veamos un ejemplo más completo que muestra cómo los métodos virtuales permiten implementar el polimorfismo:
public class Figura
{
public string Color { get; set; }
public Figura(string color)
{
Color = color;
}
// Método virtual que calcula el área
public virtual double CalcularArea()
{
return 0; // Implementación predeterminada
}
// Método virtual que describe la figura
public virtual string Describir()
{
return $"Una figura de color {Color}";
}
}
public class Circulo : Figura
{
public double Radio { get; set; }
public Circulo(string color, double radio) : base(color)
{
Radio = radio;
}
// Sobreescritura del método para calcular el área
public override double CalcularArea()
{
return Math.PI * Radio * Radio;
}
// Sobreescritura del método para describir
public override string Describir()
{
return $"Un círculo {Color} con radio {Radio} y área {CalcularArea():F2}";
}
}
public class Rectangulo : Figura
{
public double Ancho { get; set; }
public double Alto { get; set; }
public Rectangulo(string color, double ancho, double alto) : base(color)
{
Ancho = ancho;
Alto = alto;
}
// Sobreescritura del método para calcular el área
public override double CalcularArea()
{
return Ancho * Alto;
}
// Sobreescritura del método para describir
public override string Describir()
{
return $"Un rectángulo {Color} de {Ancho}x{Alto} con área {CalcularArea():F2}";
}
}
Este ejemplo muestra cómo podemos trabajar con figuras de manera polimórfica:
// Creamos una lista de figuras de diferentes tipos
List<Figura> figuras = new List<Figura>
{
new Circulo("rojo", 5),
new Rectangulo("azul", 4, 6),
new Figura("verde")
};
// Iteramos sobre todas las figuras
foreach (var figura in figuras)
{
// El método virtual correcto se llama según el tipo real
Console.WriteLine(figura.Describir());
Console.WriteLine($"Área: {figura.CalcularArea():F2}");
Console.WriteLine();
}
La salida sería:
Un círculo rojo con radio 5 y área 78.54
Área: 78.54
Un rectángulo azul de 4x6 con área 24.00
Área: 24.00
Una figura de color verde
Área: 0.00
Este es el poder del polimorfismo mediante métodos virtuales: podemos tratar objetos de diferentes tipos de manera uniforme a través de su tipo base, pero cada objeto mantiene su comportamiento específico.
Métodos con override
La palabra clave override es un componente esencial del mecanismo de polimorfismo en C#. Mientras que virtual
indica que un método puede ser sobreescrito, override
es la herramienta que utilizamos en las clases derivadas para proporcionar una implementación específica de ese método.
Sintaxis básica de override
Para sobreescribir un método virtual, debemos usar la palabra clave override
en la declaración del método en la clase derivada:
public class ClaseDerivada : ClaseBase
{
public override void MiMetodo()
{
// Nueva implementación
Console.WriteLine("Implementación en la clase derivada");
}
}
Es importante destacar que para usar override
, deben cumplirse varias condiciones:
- El método que se sobreescribe debe estar marcado como
virtual
,abstract
o ser ya un métodooverride
en la clase base - La firma del método debe ser exactamente igual (mismo nombre, parámetros y tipo de retorno)
- El nivel de accesibilidad debe ser el mismo o menos restrictivo
Llamando al método de la clase base
Uno de los aspectos más útiles al sobreescribir métodos es la capacidad de extender la funcionalidad del método base en lugar de reemplazarla completamente. Esto se logra mediante la palabra clave base
:
public class Estudiante : Persona
{
public string Carrera { get; set; }
public Estudiante(string nombre, int edad, string carrera)
: base(nombre, edad)
{
Carrera = carrera;
}
public override string ObtenerInformacion()
{
// Llamamos al método de la clase base y extendemos su funcionalidad
string infoBase = base.ObtenerInformacion();
return $"{infoBase}, Carrera: {Carrera}";
}
}
En este ejemplo, la clase Estudiante
no reemplaza completamente el comportamiento de ObtenerInformacion()
, sino que lo extiende añadiendo información específica de estudiante.
Sobreescritura vs ocultamiento (new)
Es importante distinguir entre sobreescritura (override) y ocultamiento (new) de métodos:
public class Base
{
public virtual void Metodo()
{
Console.WriteLine("Base.Metodo()");
}
}
public class Derivada1 : Base
{
// Sobreescritura - polimorfismo
public override void Metodo()
{
Console.WriteLine("Derivada1.Metodo()");
}
}
public class Derivada2 : Base
{
// Ocultamiento - no es polimorfismo
public new void Metodo()
{
Console.WriteLine("Derivada2.Metodo()");
}
}
La diferencia clave se observa cuando accedemos a estos objetos a través de una referencia del tipo base:
Base b1 = new Derivada1();
Base b2 = new Derivada2();
b1.Metodo(); // Imprime: "Derivada1.Metodo()" - Se usa la versión sobreescrita
b2.Metodo(); // Imprime: "Base.Metodo()" - Se usa la versión de la clase base
Con override
, el método que se ejecuta depende del tipo real del objeto (polimorfismo). Con new
, el método que se ejecuta depende del tipo de la referencia.
Sobreescritura de propiedades
No solo los métodos pueden ser sobreescritos; las propiedades también pueden marcarse como virtual
y sobreescribirse:
public class Producto
{
public virtual decimal Precio { get; set; }
public virtual decimal CalcularPrecioFinal()
{
return Precio * 1.21m; // Precio con IVA
}
}
public class ProductoImportado : Producto
{
private decimal _tasaImportacion = 1.10m;
// Sobreescribimos la propiedad
public override decimal Precio
{
get { return base.Precio * _tasaImportacion; }
set { base.Precio = value; }
}
// También sobreescribimos el método
public override decimal CalcularPrecioFinal()
{
// Podemos usar la implementación base
return base.CalcularPrecioFinal();
// O podríamos hacer nuestra propia implementación:
// return Precio * 1.21m;
}
}
En este ejemplo, la propiedad Precio
se sobreescribe para incluir automáticamente la tasa de importación en el getter.
Sobreescritura de métodos abstractos
Cuando sobreescribimos métodos abstract
, la mecánica es similar, pero hay una diferencia conceptual importante: los métodos abstractos deben ser sobreescritos, ya que no tienen implementación en la clase base:
public abstract class Documento
{
public string Titulo { get; set; }
// Método abstracto - sin implementación
public abstract void Imprimir();
// Método virtual - con implementación predeterminada
public virtual string GenerarEncabezado()
{
return $"Documento: {Titulo}";
}
}
public class Factura : Documento
{
public decimal Total { get; set; }
// Obligatorio implementar métodos abstractos
public override void Imprimir()
{
Console.WriteLine($"Imprimiendo factura: {Titulo}");
Console.WriteLine($"Total: {Total:C}");
}
// Opcional sobreescribir métodos virtuales
public override string GenerarEncabezado()
{
return $"FACTURA: {Titulo} - TOTAL: {Total:C}";
}
}
Cadenas de sobreescritura
Un aspecto interesante de la sobreescritura es que puede formar cadenas a través de múltiples niveles de herencia:
public class A
{
public virtual void Metodo() { Console.WriteLine("A.Metodo()"); }
}
public class B : A
{
public override void Metodo() { Console.WriteLine("B.Metodo()"); }
}
public class C : B
{
public override void Metodo() { Console.WriteLine("C.Metodo()"); }
}
Cada clase en la jerarquía puede decidir sobreescribir el método o no. Si una clase intermedia no sobreescribe el método, la implementación más cercana en la cadena de herencia se utilizará.
Sellado de métodos sobreescritos
En ocasiones, queremos permitir la sobreescritura hasta cierto punto en la jerarquía, pero evitar que las clases derivadas adicionales modifiquen el comportamiento. Para esto, podemos sellar un método sobreescrito usando la palabra clave sealed
:
public class Animal
{
public virtual string HacerSonido() { return "..."; }
}
public class Perro : Animal
{
// Sobreescribimos y sellamos el método
public sealed override string HacerSonido() { return "Guau"; }
}
public class PerroLabrador : Perro
{
// Error de compilación: no se puede sobreescribir un método sellado
// public override string HacerSonido() { return "Guau Guau"; }
}
Al marcar un método como sealed override
, estamos diciendo: "Este método puede sobreescribir el de la clase base, pero ninguna clase derivada de esta puede sobreescribirlo más".
Ejemplo práctico: sistema de notificaciones
Veamos un ejemplo más completo que muestra cómo la sobreescritura permite crear sistemas extensibles:
public class Notificacion
{
public string Mensaje { get; set; }
public string Destinatario { get; set; }
public Notificacion(string mensaje, string destinatario)
{
Mensaje = mensaje;
Destinatario = destinatario;
}
public virtual bool Validar()
{
// Validación básica
return !string.IsNullOrEmpty(Mensaje) && !string.IsNullOrEmpty(Destinatario);
}
public virtual void Enviar()
{
if (Validar())
{
Console.WriteLine($"Enviando notificación genérica a {Destinatario}: {Mensaje}");
}
else
{
Console.WriteLine("La notificación no es válida");
}
}
}
public class NotificacionEmail : Notificacion
{
public string Asunto { get; set; }
public NotificacionEmail(string mensaje, string email, string asunto)
: base(mensaje, email)
{
Asunto = asunto;
}
public override bool Validar()
{
// Primero validamos lo básico usando la implementación base
if (!base.Validar())
return false;
// Luego agregamos validación específica para email
return Destinatario.Contains("@") && !string.IsNullOrEmpty(Asunto);
}
public override void Enviar()
{
if (Validar())
{
Console.WriteLine($"Enviando email a {Destinatario}");
Console.WriteLine($"Asunto: {Asunto}");
Console.WriteLine($"Mensaje: {Mensaje}");
}
else
{
Console.WriteLine("El email no es válido");
}
}
}
public class NotificacionSMS : Notificacion
{
public NotificacionSMS(string mensaje, string telefono)
: base(mensaje, telefono)
{
}
public override bool Validar()
{
if (!base.Validar())
return false;
// Validamos que el destinatario sea un número de teléfono
return Destinatario.All(char.IsDigit) && Mensaje.Length <= 160;
}
public override void Enviar()
{
if (Validar())
{
Console.WriteLine($"Enviando SMS al {Destinatario}: {Mensaje}");
}
else
{
Console.WriteLine("El SMS no es válido");
}
}
}
Este sistema permite enviar diferentes tipos de notificaciones de manera polimórfica:
List<Notificacion> notificaciones = new List<Notificacion>
{
new Notificacion("Mensaje genérico", "Usuario"),
new NotificacionEmail("Por favor confirme su cuenta", "usuario@ejemplo.com", "Confirmación de cuenta"),
new NotificacionSMS("Su código de verificación es 1234", "555123456")
};
foreach (var notificacion in notificaciones)
{
// Polimorfismo en acción - cada tipo ejecuta su propia versión
notificacion.Enviar();
Console.WriteLine();
}
Consideraciones de diseño
Al trabajar con métodos override
, es importante tener en cuenta algunas consideraciones de diseño:
- Principio de sustitución de Liskov: Una clase derivada debe poder sustituir a su clase base sin alterar el comportamiento esperado del programa.
- Coherencia semántica: La implementación sobreescrita debe mantener la semántica general del método base, aunque con comportamiento específico.
- Evitar efectos secundarios inesperados: Especialmente cuando se llama a
base.Metodo()
, asegúrate de que no haya efectos secundarios no deseados. - Documentación clara: Documenta claramente cómo tu implementación sobreescrita difiere de la implementación base.
Errores comunes al sobreescribir métodos
Algunos errores frecuentes al trabajar con override
incluyen:
- Olvidar la palabra clave
override
, lo que resulta en ocultamiento (new
) en lugar de sobreescritura - Intentar sobreescribir un método que no está marcado como
virtual
oabstract
- Cambiar la firma del método (parámetros o tipo de retorno)
- No mantener la compatibilidad semántica con el método base
public class EjemploError : Base
{
// Error: falta override, esto es ocultamiento, no sobreescritura
public void MetodoVirtual() { }
// Error: el método base no es virtual
public override void MetodoNoVirtual() { }
// Error: firma diferente (parámetro adicional)
public override void OtroMetodoVirtual(int parametroExtra) { }
}
La sobreescritura de métodos es una herramienta fundamental para implementar el polimorfismo en C#, permitiendo que las clases derivadas proporcionen implementaciones específicas mientras mantienen una interfaz común a través de la jerarquía de clases.
Ejercicios de esta lección Métodos virtuales y sobrecarga
Evalúa tus conocimientos de esta lección Métodos virtuales y sobrecarga con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.
CRUD en C# de modelo Customer sobre una lista
Arrays y listas
Objetos
Excepciones
Eventos
Lambdas
Diccionarios en C#
Variables y constantes
Tipos de datos
Herencia
Operadores
Uso de consultas LINQ
Clases y encapsulación
Uso de consultas LINQ
Excepciones
Control de flujo
Eventos
Diccionarios
Tipos de datos
Conjuntos, colas y pilas
Lambdas
Conjuntos, colas y pilas
Uso de async y await
Tareas
Constructores y destructores
Operadores
Arrays y listas
Polimorfismo
Polimorfismo
Variables y constantes
Proyecto colecciones y LINQ en C#
Clases y encapsulación
Creación de proyecto C#
Uso de async y await
Funciones
Delegados
Delegados
Constructores y destructores
Objetos
Control de flujo
Funciones
Tareas
Proyecto sintaxis en C#
Herencia C Sharp
OOP en C Sharp
Diccionarios
Introducción a C#
Todas las lecciones de CSharp
Accede a todas las lecciones de CSharp y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Introducción A C#
Introducción Y Entorno
Creación De Proyecto C#
Introducción Y Entorno
Variables Y Constantes
Sintaxis
Tipos De Datos
Sintaxis
Operadores
Sintaxis
Control De Flujo
Sintaxis
Funciones
Sintaxis
Estructuras De Control Iterativo
Sintaxis
Interpolación De Strings
Sintaxis
Estructuras De Control Condicional
Sintaxis
Manejo De Valores Nulos
Sintaxis
Clases Y Encapsulación
Programación Orientada A Objetos
Objetos
Programación Orientada A Objetos
Constructores Y Destructores
Programación Orientada A Objetos
Herencia
Programación Orientada A Objetos
Polimorfismo
Programación Orientada A Objetos
Genéricos
Programación Orientada A Objetos
Métodos Virtuales Y Sobrecarga
Programación Orientada A Objetos
Clases Abstractas
Programación Orientada A Objetos
Interfaces
Programación Orientada A Objetos
Propiedades Y Encapsulación
Programación Orientada A Objetos
Métodos De Extensión
Programación Orientada A Objetos
Clases Y Objetos
Programación Orientada A Objetos
Clases Parciales
Programación Orientada A Objetos
Miembros Estáticos
Programación Orientada A Objetos
Tuplas Y Tipos Anónimos
Programación Orientada A Objetos
Arrays Y Listas
Colecciones Y Linq
Diccionarios
Colecciones Y Linq
Conjuntos, Colas Y Pilas
Colecciones Y Linq
Uso De Consultas Linq
Colecciones Y Linq
Linq Avanzado
Colecciones Y Linq
Colas Y Pilas
Colecciones Y Linq
Conjuntos
Colecciones Y Linq
Linq Básico
Colecciones Y Linq
Delegados Funcionales
Programación Funcional
Records
Programación Funcional
Expresiones Lambda
Programación Funcional
Linq Funcional
Programación Funcional
Fundamentos De La Programación Funcional
Programación Funcional
Pattern Matching
Programación Funcional
Testing Unitario Con Xunit
Testing
Excepciones
Excepciones
Delegados
Programación Asíncrona
Eventos
Programación Asíncrona
Lambdas
Programación Asíncrona
Uso De Async Y Await
Programación Asíncrona
Tareas
Programación Asíncrona
En esta lección
Objetivos de aprendizaje de esta lección
- Comprender la diferencia entre sobrecarga y sobreescritura de métodos en C#.
- Aprender a declarar y utilizar métodos virtuales para habilitar el polimorfismo.
- Saber cómo usar la palabra clave override para proporcionar implementaciones específicas en clases derivadas.
- Identificar las reglas y limitaciones de los métodos virtuales y sobreescritos.
- Aplicar conceptos de polimorfismo mediante ejemplos prácticos y jerarquías de clases.