Sobrecarga de Operadores
Parte da seção Programação Orientada a Objetos do Journey de C# da Coddy — lição 36 de 70.
A sobrecarga de operadores permite que você defina como operadores como +, - ou == se comportam com suas classes personalizadas. Em vez de chamar métodos como point1.Add(point2), você pode escrever o mais natural point1 + point2.
Para sobrecarregar um operador, você cria um método estático especial usando a palavra-chave 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);
}
}Agora você pode adicionar vetores naturalmente:
Vector v1 = new Vector(3, 4);
Vector v2 = new Vector(1, 2);
Vector v3 = v1 + v2; // X = 4, Y = 6O método deve ser public static, e pelo menos um parâmetro deve ser o tipo que o contém. Você pode sobrecarregar operadores aritméticos (+, -, *, /), operadores de comparação (==, !=, <, >) e operadores unários (-, !, ++).
Observe que os operadores de comparação devem ser sobrecarregados em pares - se você definir ==, você também deve definir !=.
Use a sobrecarga de operadores quando ela tornar seu código mais intuitivo, particularmente para tipos matemáticos como vetores, números complexos ou dinheiro. Evite-a quando o significado da operação não for imediatamente óbvio.
Desafio
FácilVamos construir uma classe Fraction que torne o trabalho com frações natural por meio da sobrecarga de operadores. Em vez de chamar métodos como fraction1.Add(fraction2), você poderá escrever o intuitivo fraction1 + fraction2.
Você organizará seu código em dois arquivos:
Fraction.cs: Crie uma classeFractionno namespaceMathque represente uma fração com um numerador e um denominador. Sua fração deve ter:- Duas propriedades inteiras somente leitura:
NumeratoreDenominator - Um construtor que aceita o numerador e o denominador (nessa ordem)
- Um operador
+sobrecarregado que soma duas frações usando a fórmula:(a/b) + (c/d) = (a*d + c*b) / (b*d) - Um operador
*sobrecarregado que multiplica duas frações:(a/b) * (c/d) = (a*c) / (b*d) - Um operador
==sobrecarregado que retornatruese duas frações forem iguais (use a multiplicação cruzada para comparar:a*d == c*b) - Um operador
!=sobrecarregado (obrigatório ao sobrecarregar==) que retorna o oposto de== - Um método
GetDisplay()que retorna a fração como uma string no formato"{Numerator}/{Denominator}"
- Duas propriedades inteiras somente leitura:
Program.cs: No seu arquivo principal, crie duas frações usando valores de entrada. Demonstre os operadores sobrecarregados somando-os, multiplicando-os e verificando se são iguais. Imprima os resultados para mostrar seus operadores funcionando naturalmente.
Você receberá quatro entradas:
- Numerador da primeira fração (inteiro)
- Denominador da primeira fração (inteiro)
- Numerador da segunda fração (inteiro)
- Denominador da segunda fração (inteiro)
Imprima a saída neste formato:
Fraction 1: {GetDisplay()}
Fraction 2: {GetDisplay()}
Sum: {GetDisplay()}
Product: {GetDisplay()}
Are equal: {True/False}Por exemplo, se as entradas forem 1, 2, 2 e 4, a saída deve ser:
Fraction 1: 1/2
Fraction 2: 2/4
Sum: 8/8
Product: 2/8
Are equal: TrueObserve como 1/2 e 2/4 são reconhecidos como iguais porque 1*4 == 2*2. A soma e o produto são calculados sem simplificação - tudo bem para este desafio. A beleza está na naturalidade com que você agora pode trabalhar com frações usando operadores familiares!
Folha de consulta
A sobrecarga de operadores permite que você defina um comportamento personalizado para operadores como +, -, *, == com suas classes.
Para sobrecarregar um operador, crie um método public static usando a palavra-chave operator. Pelo menos um parâmetro deve ser do tipo que o contém:
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);
}
}Uso:
Vector v1 = new Vector(3, 4);
Vector v2 = new Vector(1, 2);
Vector v3 = v1 + v2; // X = 4, Y = 6Você pode sobrecarregar:
- Operadores aritméticos:
+,-,*,/ - Operadores de comparação:
==,!=, <code><,(devem ser sobrecarregados em pares) - Operadores unários:
-,!,++
Ao sobrecarregar ==, você também deve sobrecarregar !=:
public static bool operator ==(Vector a, Vector b)
{
return a.X == b.X && a.Y == b.Y;
}
public static bool operator !=(Vector a, Vector b)
{
return !(a == b);
}Experimente você mesmo
using System;
using Math;
class Program
{
public static void Main(string[] args)
{
// Lê a entrada para a primeira fração
int num1 = Convert.ToInt32(Console.ReadLine());
int den1 = Convert.ToInt32(Console.ReadLine());
// Lê a entrada para a segunda fração
int num2 = Convert.ToInt32(Console.ReadLine());
int den2 = Convert.ToInt32(Console.ReadLine());
// TODO: Criar dois objetos Fraction usando os valores de entrada
// TODO: Usar o operador + sobrecarregado para somar as frações
// TODO: Usar o operador * sobrecarregado para multiplicar as frações
// TODO: Usar o operador == sobrecarregado para verificar a igualdade
// TODO: Imprimir a saída no formato exigido:
// Fraction 1: {GetDisplay()}
// Fraction 2: {GetDisplay()}
// Sum: {GetDisplay()}
// Product: {GetDisplay()}
// Are equal: {True/False}
}
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de POO
Arquivos ExternosNamespaces e DiretivasIntrodução a Classes e ObjetosA Palavra-chave 'this'Métodos e ParâmetrosCampos vs PropriedadesConstrutoresInicializadores de ObjetosRecapitulação - Calculadora Simples4Herança
Sintaxe Básica de Herança (:)A Palavra-chave 'base'Palavras-chave Virtual e OverrideClasses SeladasA Classe Base 'object'Recapitulação - Hierarquia de Funcionários7Recursos Avançados
Sobrecarga de OperadoresIndexadores (this[])Sobrescrita de ToString()Métodos de ExtensãoRecapitulação - Lista Personalizada10Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoSingleton Thread-SafePadrão FactoryPadrão Observer (Eventos)Padrão Strategy2Propriedades e Membros Estáticos
Propriedades AutoimplementadasPropriedades de Apenas Leitura/EscritaCampos e Métodos EstáticosClasses EstáticasMembros com Corpo de Expressão5Polimorfismo e Interfaces
Polimorfismo: Compilação vs ExecuçãoInterface vs Classe AbstrataMúltiplas InterfacesInterfaces ExplícitasUpcasting e DowncastingRecapitulação - Calculadora de Formas8Conceitos Avançados de POO
Composição sobre HerançaGenerics (Classes e Métodos)Delegates e EventosAtributos e ReflectionIDisposable e a Instrução usingFundamentos de Injeção de Dependência11Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão Composite3Arquitetura de Classes
Dados de Instância vs EstáticosPalavras-chave 'readonly' e 'const'Campos de SuporteRecapitulação - Gerenciador de Conta Bancária6Encapsulamento
Modificadores de AcessoPropriedades para EncapsulamentoImplementação de Ocultação de DadosPadrões de ImutabilidadeRecapitulação - Registros de Estudantes9Argumentos Variáveis
A Palavra-chave 'params'Parâmetros OpcionaisArgumentos NomeadosSobrecarga de Métodos