Clases y estructuras bien formadas, Parte III

by cristian 21/04/2008 4:41:17

Puff, teníamos tiempo no conversábamos sobre este tema. La última vez que hablamos de estructuras y clases bien formadas fue para implementar operadores binarios simples. Hoy expandiremos un poco más la conversación y seguiremos hablando de operadores en clases. Hablaremos hoy sobre operadores unarios y operadores lógicos.

Operadores Unarios

Quién no recordará la expresión variable++ ó ++variable, para aquellos que por alguna razón olvidaron la diferencia, el operador variable++ especifica que a la variable se le agregará una unidad después de que su valor sea obtenido y ++variable indica que a la variable se le añadirá una unidad antes de que su valor sea obtenido. La mejor forma de ver la diferencia es de la siguiente manera:

   1: using System;
   2:  
   3: public class TestValues
   4: {
   5:     public static void Main(string[] args)
   6:     {
   7:         int a = 1;
   8:         int b = a++;
   9:         int c = ++a;
  10:         Console.WriteLine("a: {0} b: {1} c: {2}", a, b, c);
  11:     }
  12: }

Ahora clara la diferencia verdad?, bien, vamos a intentar lo mismo para el overload del operador unario complex++ en nuestra clase para números complejos, imaginemos que esto representaría el equivalente a sumar un número complejo mas 1+0i, tomando esto en cuenta modificamos nuestra clase y nuestra unidad de pruebas:

   1: [Test]
   2: public void TestUnaryAddOperator()
   3: {
   4:     Complex cplx = new Complex(4,2);
   5:     Complex cplxPost = cplx++; // debería ser 4,2
   6:     Complex cplxPre = ++cplx; // debería ser 6,2 == cplx01
   7:  
   8:     Assert.That(cplxPost.RealPart, Is.EqualTo(4));
   9:     Assert.That(cplxPre.RealPart, Is.EqualTo(6));
  10:     Assert.That(cplx.RealPart, Is.EqualTo(6));
  11: }

Ahora definimos el operador en la clase:

   1: class ComplexNumber
   2: {
   3:     // Todas las definiciones anteriores van aquí
   4:     public static Complex operator++(Complex baseCplx)
   5:     {
   6:         return AddComplex(baseCplx, new Complex(1,0));
   7:     }
   8: }

Alguien preguntará, cómo es posible definir un pre/post operador unario con un sólo operador y no modificar el la clase que llama al mismo tiempo? Este es un comportamiento que desconcertará a los programadores de C++ a simple vista (si es usted programador C++ sabrá de lo que le hablo). El secreto está en que el compilador crea "copias temporales" del objeto y en base a eso las asigna, la belleza de todo esto es que con un sólo operador implementamos tanto la forma prefija como la postfija. Interesante no? además si usted recuerda a nuestro amigo C++ sabrá que modificar this en ese momento no es muy llamativo.

Operadores de Casting

Bien, alguien ya a estas alturas habrá dicho "hey, y no sería más fácil hacer algo como (4+5i) + 1 = (5+5i) siendo 1 automáticamente el equivalente a 1+0i????", bien, este precavido lector tiene toda la razón del porqué preguntar, si tiene mayor sentido y si se puede lograr, de hecho en la .Net a esto se les llama operadores de casting. Antes de proseguir creo que es importante hacer notar que existen dos tipos de casting, el implícito y el explícito.

Los operadores implícitos de conversión son aquellos que no necesitan ser "casteados" en el código, por ejemplo, convertir un entero a un número real, sin embargo si queremos convertir un número real a un entero debemos explícitamente decirle que el resultado será un entero, a esto le llamamos conversión explícita. Creo que esto se debe a que las operaciones implícitas de conversión nunca deben producir una excepción y en las explícitas esto está permitido, en el caso de un entero a un real asumimos que siempre hay espacio en la data que contiene un entero para que "entre" un real, sin embargo puede ser que el número real sea más grande que la capacidad de un entero. Vamos comprendiendo?

Bien, para demostrar nuestro punto asumimos un comportamiento similar, diremos que se puede implícitamente castear un entero a un número complejo pero necesitamos explícitamente castear el número complejo a un número entero. Asumiendo que un número entero es equivalente a num + 0i entonces pasamos a representarlo en una prueba:

   1: [Test]
   2: public void TestImplicitIntComplexCasting()
   3: {
   4:     Complex cplx = 1;
   5:  
   6:     Assert.That(cplx.RealPart, Is.EqualTo(1));
   7:     Assert.That(cplx.ImaginaryPart, Is.EqualTo(0));
   8: }

Tomando en cuenta que al transformar un número complejo a un número entero es igual a la raiz cuadrada de la suma de las dos partes cuadradas (imaginaria y real). Para simplificar nuestro ejemplo tomaremos en cuenta que solo podremos castear de Complex a un número real (double).

   1: public static implicit operator ComplexNumber(int num)
   2: {
   3:     return new ComplexNumber(num, 0);
   4: }
   5:  
   6: public static explicit operator double(Complex cplx)
   7: {
   8:     return Math.Sqrt(Math.Pow(cplx.RealPart, 2) + Math.Pow(cplx.ImaginaryPart, 2));
   9: }

Ahora probamos y todo debe funcionar fantásticamente. Recuerden, debemos crear overloading de operadores para solo aquellas clases que las necesitan, o sea, todo esto tiene sentido si en su dominio tiene sentido hacer tales operaciones matemáticas y queremos simplificarlo de esta forma, de otra manera NO sobrecarguen operadores.

Operadores Unarios Permitidos

A diferencia de C++, en C# no se pueden crear operadores unarios o binarios "nuevos" (crear operadores es una práctica bastante común en bases de datos como PostgreSQL por ejemplo). Estamos restringidos a los operadores siguientes:

Unarios Binarios
+ +
- -
! *
~ /
++ %
-- &
true |
false ^
  <<
  >>
  ==, !=
  >, <
  >=, <=

Los únicos unarios que nos hacen falta son los booleanos lógicos, los cuales junto con los operadores de comparación veremos en la siguiente parte, esta vez espero tenerla lista pronto. Hasta entonces me despido! Como siempre cualquier duda están a sólo un par de correos de distancia.

Technorati Tags: ,,
Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Actualmente calificado con 4.0 por 2 personas

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

.net | programming

Publicaciones relacionadas

Powered by BlogEngine.NET 1.3.1.0
Theme by Mads Kristensen

About me!

Name of author Cristian Prieto
Software Architect and a .Net fan

E-mail me Send mail

Calendar

<<  noviembre 2008  >>
lumamijuvido
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

View posts in large calendar

Comentarios recientes

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2008

Sign in