Sobrecarga de operadores
Parte de la sección Programación Orientada a Objetos del Journey de C# de Coddy — lección 36 de 70.
La sobrecarga de operadores te permite definir cómo se comportan los operadores como +, - o == con tus clases personalizadas. En lugar de llamar a métodos como point1.Add(point2), puedes escribir el más natural point1 + point2.
Para sobrecargar un operador, se crea un método estático especial utilizando la palabra clave operator:
public class Vector
{
public int X { get; }
public int Y { get; }
public Vector(int x, int y)
{
X = x;
Y = y;
}
public static Vector operator +(Vector a, Vector b)
{
return new Vector(a.X + b.X, a.Y + b.Y);
}
}Ahora puedes sumar vectores de forma natural:
Vector v1 = new Vector(3, 4);
Vector v2 = new Vector(1, 2);
Vector v3 = v1 + v2; // X = 4, Y = 6El método debe ser public static, y al menos un parámetro debe ser el tipo contenedor. Puedes sobrecargar los operadores aritméticos (+, -, *, /), los operadores de comparación (==, !=, <, >) y los operadores unarios (-, !, ++).
Ten en cuenta que los operadores de comparación deben sobrecargarse en pares: si defines ==, también debes definir !=.
Usa la sobrecarga de operadores cuando haga que tu código sea más intuitivo, especialmente para tipos matemáticos como vectores, números complejos o dinero. Evítala cuando el significado de la operación no sea inmediatamente obvio.
Desafío
FácilVamos a construir una clase Fraction que haga que trabajar con fracciones se sienta natural a través de la sobrecarga de operadores. En lugar de llamar a métodos como fraction1.Add(fraction2), podrás escribir el intuitivo fraction1 + fraction2.
Organizarás tu código en dos archivos:
Fraction.cs: Crea una claseFractionen el espacio de nombresMathque represente una fracción con un numerador y un denominador. Tu fracción debe tener:- Dos propiedades de enteros de solo lectura:
NumeratoryDenominator - Un constructor que acepte el numerador y el denominador (en ese orden)
- Un operador
+sobrecargado que sume dos fracciones usando la fórmula:(a/b) + (c/d) = (a*d + c*b) / (b*d) - Un operador
*sobrecargado que multiplique dos fracciones:(a/b) * (c/d) = (a*c) / (b*d) - Un operador
==sobrecargado que devuelvatruesi dos fracciones son iguales (usa la multiplicación cruzada para comparar:a*d == c*b) - Un operador
!=sobrecargado (requerido cuando sobrecargas==) que devuelva lo opuesto a== - Un método
GetDisplay()que devuelva la fracción como una cadena en el formato"{Numerator}/{Denominator}"
- Dos propiedades de enteros de solo lectura:
Program.cs: En tu archivo principal, crea dos fracciones usando valores de entrada. Demuestra los operadores sobrecargados sumándolos, multiplicándolos y comprobando si son iguales. Imprime los resultados para mostrar tus operadores funcionando de manera natural.
Recibirás cuatro entradas:
- Numerador de la primera fracción (entero)
- Denominador de la primera fracción (entero)
- Numerador de la segunda fracción (entero)
- Denominador de la segunda fracción (entero)
Imprime la salida en este formato:
Fraction 1: {GetDisplay()}
Fraction 2: {GetDisplay()}
Sum: {GetDisplay()}
Product: {GetDisplay()}
Are equal: {True/False}Por ejemplo, si las entradas son 1, 2, 2, y 4, la salida debería ser:
Fraction 1: 1/2
Fraction 2: 2/4
Sum: 8/8
Product: 2/8
Are equal: TrueObserva cómo 1/2 y 2/4 son reconocidos como iguales porque 1*4 == 2*2. La suma y el producto se calculan sin simplificación; eso está bien para este desafío. ¡La belleza reside en lo natural que ahora puedes trabajar con fracciones usando operadores familiares!
Pruébalo tú mismo
using System;
using Math;
class Program
{
public static void Main(string[] args)
{
// Leer la entrada para la primera fracción
int num1 = Convert.ToInt32(Console.ReadLine());
int den1 = Convert.ToInt32(Console.ReadLine());
// Leer la entrada para la segunda fracción
int num2 = Convert.ToInt32(Console.ReadLine());
int den2 = Convert.ToInt32(Console.ReadLine());
// TODO: Crear dos objetos Fraction utilizando los valores de entrada
// TODO: Usar el operador + sobrecargado para sumar las fracciones
// TODO: Usar el operador * sobrecargado para multiplicar las fracciones
// TODO: Usar el operador == sobrecargado para comprobar la igualdad
// TODO: Imprimir la salida en el formato requerido:
// Fraction 1: {GetDisplay()}
// Fraction 2: {GetDisplay()}
// Sum: {GetDisplay()}
// Product: {GetDisplay()}
// Are equal: {True/False}
}
}
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
1Fundamentos de OOP
Archivos externosNamespaces y directivasIntro a clases y objetosLa palabra clave 'this'Métodos y parámetrosCampos vs PropiedadesConstructoresInicializadores de objetosResumen - Calculadora simple4Herencia
Sintaxis básica de herencia (:)La palabra clave 'base'Palabras clave Virtual y OverrideClases selladas (Sealed)La clase base 'object'Resumen: Jerarquía de empleados7Características avanzadas
Sobrecarga de operadoresIndexadores (this[])Sobrescritura de ToString()Métodos de extensiónResumen - Lista personalizada10Patrones de diseño - Parte 1
Introducción a los patrones de diseñoSingleton Thread-SafePatrón FactoryPatrón Observer (Eventos)Patrón Strategy2Propiedades y miembros estáticos
Propiedades autoimplementadasPropiedades de solo lectura y escrituraCampos y métodos estáticosClases estáticasMiembros con cuerpo de expresión5Polimorfismo e Interfaces
Polimorfismo: Compilación vs. EjecuciónInterfaz vs. Clase AbstractaInterfaces MúltiplesInterfaces ExplícitasUpcasting y DowncastingRepaso: Calculadora de Figuras8Conceptos avanzados de POO
Composición sobre herenciaGenéricos (clases y métodos)Delegados y eventosAtributos y ReflexiónIDisposable y la sentencia usingFundamentos de Inyección de dependencias11Patrones de diseño, parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón Composite3Arquitectura de clases
Datos de instancia vs. estáticosPalabras clave 'readonly' y 'const'Campos de respaldoResumen - Gestor de cuentas bancarias6Encapsulamiento
Modificadores de accesoPropiedades para el encapsulamientoImplementación de ocultamiento de datosPatrones de inmutabilidadRepaso - Registros de estudiantes