Sobrecarga (overloading) de operadores. O que vem a ser isso?
Se você esta vindo de uma linguagem procedural como Clipper, Dbase , Basic, Cobol, etc, ou se está começando agora, tendo o C# como sua primeira linguagem de programação, pode estranhar o termo. Mas é apenas uma questão de prática.
A sobrecarga (Overload) é a habilidade de poder definir diversas propriedades, métodos ou procedimentos em uma classe com o mesmo nome, mas parâmetros diferentes.
Você entendeu? Bom, vou ser mais claro… Se você criar dois procedimentos em seu aplicativo com o mesmo nome e com parâmetros diferentes estará usando sobrecarga.
Você deve estar se perguntando: “como posso criar dois procedimentos com o mesmo nome? Como vou diferenciá-los?”. Você vai diferenciar os métodos/procedimentos pela lista de parâmetros que eles vão possuir, isto é , os métodos/procedimentos terão parâmetros diferentes. Vou dar um exemplo:
Suponha que você precise criar uma classe com um método que retorne o valor da área de um quadrado, só que este método vai poder aceitar como parâmetro uma string ou um número:
[csharp]
public double CalculaArea(double lado)
{
return lado * lado;
}[/csharp]
[csharp]
public double CalculaArea(string lado)
{
double ld = 0;
ld = Convert.ToDouble(lado);
return ld * ld;
}[/csharp]
Aqui temos dois métodos com o mesmo nome (CalculaArea), mas que possuem parâmetros diferentes (tipo de dados diferentes) que fornecem o mesmo resultado. Pois bem, podemos fazer a mesma coisa para operadores na linguagem C#.
A linguagem C#, assim como muitas linguagens orientadas a objetos, permitem a sobrecarga de operadores, ou seja a capacidade de redefinir os operadores de uma classe.
Nem todos os operadores podem ser sobrecarregados, e existem restrições relativas a quando certos operadores podem ser sobrecarregados, como a definição dos operadores == e /=.
Através da sobrecarga de operadores podemos realizar operações complexas, através de argumentos de funções, e isso nos permite escrever um código muito mais intuitivo e legível.
Para modificar um operador na linguagem C# usamos a seguinte sintaxe:
[modificadores*][type] operator [operator] (parâmetros){(…)}
Os operadores uniários recebem somente um parâmetro e os operadores binários recebem dois parâmetros, sendo que em cada caso um dos parâmetros deve ser do tipo da classe que esta redefinindo o operador.
Operador uniário:
[csharp]
public static ret-type operator op(parameter-type operand)
{
}[/csharp]
Operador binário:
[csharp]
public static ret-type operator op(parameter-type operand1, parameter-type operand1)
{
}[/csharp]
Obs: Os operadores redefinidos devem ser public static.
Vejamos um exemplo prático onde iremos realizar a sobrecarga do operador ++: abra o Visual C# 2010 Express Edition e crie um novo projeto do tipo Console Application com o nome SobreCargaOperadores.
A seguir, defina o seguinte código na classe Program.cs:
[csharp]
using System;
namespace SobrecargarOperadores
{
class Program
{
static void Main(string[] args)
{
Calculo i = new Calculo(100, 200, 300);
Calculo j = new Calculo(5, 10, 3);
i++;
i.MostraResultado();
j++;
j.MostraResultado();
Console.WriteLine();
}
}
class Calculo
{
int a, b, c;
public Calculo()
{
a = b = c = 0;
}
public Calculo(int x, int y, int z)
{
a = x;
b = y;
c = z;
}
public static Calculo operator ++(Calculo op1)
{
op1.a++;
op1.b++;
op1.c++;
return op1;
}
public void MostraResultado()
{
Console.WriteLine(a + "," + b + "," + c);
Console.ReadLine();
}
}
}[/csharp]
Aqui criamos a classe Calculo e redefinimos o operador ++ para realizar o incremento em uma unidade dos argumentos recebidos.
Executando o projeto teremos:
Muito simples, não é mesmo?! Vamos agora realizar a sobrecarga de operadores binários para os operadores + , – , / e * (adição, subtração, divisão e multiplicação).
No menu File clique em Add -> Project e a seguir informe o nome OperadoresBInarios;
Defina a seguir o código abaixo na classe Program.cs:
[csharp]
using System;
namespace OperadoresBinarios
{
class Program
{
static void Main(string[] args)
{
Calculo i = new Calculo(10, 20, 30);
Calculo j = new Calculo(5, 10, 15);
Calculo k = new Calculo();
Console.WriteLine("Sobrecarga de Operadores");
Console.WriteLine("i = 10, 20, 30");
Console.WriteLine("j = 5, 10, 15");
Console.WriteLine();
//adição
k = i + j;
Console.WriteLine("+");
k.MostraResultado();
Console.WriteLine();
//subtração
k = i – j;
Console.WriteLine("-");
k.MostraResultado();
Console.WriteLine();
//multiplicação
k = i * j;
Console.WriteLine("*");
k.MostraResultado();
Console.WriteLine();
//divisão
k = i / j;
Console.WriteLine("/");
k.MostraResultado();
Console.WriteLine();
}
}
class Calculo
{
int a, b, c;
public Calculo()
{
a = b = c = 0;
}
public Calculo(int x, int y, int z)
{
a = x;
b = y;
c = z;
}
public static Calculo operator +(Calculo op1, Calculo op2)
{
Calculo calc = new Calculo();
calc.a = op1.a + op2.a;
calc.b = op1.b + op2.b;
calc.c = op1.c + op2.c;
return calc;
}
public static Calculo operator -(Calculo op1, Calculo op2)
{
Calculo calc = new Calculo();
calc.a = op1.a – op2.a;
calc.b = op1.b – op2.b;
calc.c = op1.c – op2.c;
return calc;
}
public static Calculo operator *(Calculo op1, Calculo op2)
{
Calculo calc = new Calculo();
calc.a = op1.a * op2.a;
calc.b = op1.b * op2.b;
calc.c = op1.c * op2.c;
return calc;
}
public static Calculo operator /(Calculo op1, Calculo op2)
{
Calculo calc = new Calculo();
calc.a = op1.a / op2.a;
calc.b = op1.b / op2.b;
calc.c = op1.c / op2.c;
return calc;
}
public void MostraResultado()
{
Console.WriteLine(a + "," + b + "," + c);
Console.ReadLine();
}
}
}[/csharp]
Aqui temos a sobrecarga dos operadores +, -, / e *.
Executando o projeto teremos:
Se os operadores de comparação (==) forem sobrecarregados, essa sobrecarga deve ser feita aos pares; ou seja, se for sobrecarregado o operador == também se deve sobrecarregar o operador !=. O mesmo vale para os operadores < e >, e <= e >=.
Outro fato importante é que se, por exemplo, você está sobrecarregando o operador ==, não pode usar (a == b), (a == null) ou (b == null) para verificar a igualdade de referência dentro da sobrecarga.
Isso resulta em uma chamada para o operador sobrecarregado ==, que é o mesmo que voltar a chamar o operador que você está redefinindo e como resultado há um loop infinito. UseReferenceEquals ou converta o tipo de objeto para evitar isso.
Pegue o projeto completo aqui: SobrecargarOperadores.zip