lunes, 22 de septiembre de 2014

Pregunta C# (9 de 20): ¿Cuál es la Diferencia entre Funciones Abstractas y Virtuales?

Índice

0. Introducción
1. Contexto
2. Palabras Clave: abstract, y virtual
2.1 abstract
2.2 virtual
3. Resumen de diferencias
4. Recursos
5. Conclusiones
6. Glosario
7. Literatura & Enlaces

0. Introducción

Pasemos a la pregunta número nueve del curso de Microsoft Virtual Academy: Twenty C# Questions Explained. En esta ocasión estudiaremos los detalles que diferencian un miembro de tipo virtual y abstracto. Se hace necesario tratar con dos de las palabras claves del lenguaje de programación C#: abstract, y virtual, para comprender las diferencias. Veremos, además, cómo estas dos construcciones permiten crear una jerarquía de herencia consistente a nuestro modelo del mundo del problema.

1. Contexto

El lenguaje de programación C# cuenta con construcciones especializadas para el mecanismo de herencia y polimorfismo que permiten alcanzar un nivel de granularidad adicional sobre las funciones (en especial los métodos) de un tipo de dato. Esto quiere decir, que el programador es capaz de especificar los métodos (por ejemplo) que deberían poseer una implementación a partir de una jerarquía de herencia o la omisión total de del cuerpo de implementación.

Continuando, cuando nos referimos a la omisión total del cuerpo de implementación de un método estamos hablando de métodos abstractos. Este tipo de métodos son declarados en la implementación de una clase abstracta y deben implementarse en el tipo derivado; en caso de no ser así el compilador lanzará un error informando sobre el no cumplimiento del contrato de herencia entre una clase abstracta y una clase concreta.

Por otro lado, como veremos más adelante en ejemplos de uso, un método marcado como virtual puede o no contener una implementación particular en un tipo derivado.

Para no extendernos más en este contexto, sugiero la lectura de estos dos artículos que nos ilustran más acerca de clases y miembros abstractos, y miembros función virtuales:

2. Palabras Clave: abstract, y virtual

2.1 abstract

Una clase puede ser marcada con el modificador abstract [4] para ser tratada como una clase abstracta; esto quiere decir que sus miembros, en particular los métodos, también marcados como abstract carecen de una implementación particular (abstracta). Veamos un ejemplo partiendo de la siguiente jerarquía de herencia:
Jerarquía de herencia de Calculadora
Figura 1. Jerarquía de herencia de Calculadora.
En esta jerarquía de herencia la clase abstracta Calculadora puede contener el método abstracto llamado Sumar. Este método debe ser implementado por las clases derivadas:
  • CalculadoraEstandar, y 
  • CalculadoraTrigonometrica
Una versión de ejemplo de la clase Calculadora sería:

public abstract class Calculadora
{
public abstract double Sumar(double a, double b);
      // Resto de la implementación...
}

Ahora, cualquiera de las dos clases concretas que herede de esta clase deben crear una implementación concreta para el método abstracto Sumar. Veamos:

public class CalculadoraEstandar : Calculadora
{
public double Sumar(double a, double b)
{
return a + b;
}

// Resto de la implementación...
}

En caso de omitirse la implementación de este método el compilador de C# generará un error.

2.2 virtual

La palabra clave virtual [5] se usa como modificador de un miembro de un tipo para especificar que puede ser sobreescrito en cualquier tipo derivado (subclase). Su sobreescritura es opcional y puede pertenecer tanto a una clase concreta como una clase abstracta (esta es una de las principales diferencias frente abstract).


Ahora vemos un ejemplo de uso en donde nos puede resultar útil este modificador. Enfoquémonos en la jerarquía de herencia Figura:
Jerarquía de herencia Figura
Figura 2. Jerarquía de herencia Figura.
El método Area de la clase abstracta base Figura se declara de la siguiente manera:

public virtual double Area()
{
return x * y;
}

Esta es la implementación base para cualquiera de las clases derivadas Circulo, Esfera, y Cilindro. Sin embargo, cada una de estas clases puede optar por sobreescribir el método Area para el cálculo del área según la dimensión; por ejemplo:

public class Esfera : Figura
{
public override double Area ()
{
return 4 * Math.PI * x * x;
}
}

Notemos como la clase Esfera sobreescribe el método Area especificando su propia implementación. Esto se logra con el modificador override.

Finalmente, vale aclarar que la sobreescritura en las clases derivadas es totalmente opcional.

3. Resumen de Diferencias

Funciones abstractas:
  • Declaración únicamente dentro de clases abstractas.
  • Sólo se puede incluir la definición de la firma del método, y no su implementación.
  • Debe ser sobreescrita por cualquiera de las clases derivadas a partir de la clase base abstracta.
Funciones virtuales:
  • Puede ser declarada tanto en una clase abstracta como en una clase concreta.
  • El método puede contener u omitir la implementación en la clase base donde es declarado.
  • La sobreescritura es opcional por cualquier tipo derivado en una jerarquía de herencia.

4. Recursos

Este es el vídeo en donde el equipo de expertos (Gerry O'Brein y Paul Pardi) de MVA responden y explican esta pregunta:

5. Conclusiones

Hemos comprendido las diferencias esenciales entre las funciones (métodos en particular) abstractas y virtuales. En el primer caso podemos concluir que un método abstracto aparece en una clase abstracta, no debe contener implementación, y debe ser sobreescrito por una clase concreta que herede de la clase abstracta. En el caso de un método virtual, puede ser miembro tanto de una clase abstracta como de una clase concreta, una clase derivada puede (opcional) sobreescribir la implementación del método de la clase base. En la próxima pregunta C# comprenderemos la diferencia entre las palabras clave ref y out.

6. Glosario

  • Clase abstracta
  • Clase concreta
  • Herencia
  • Polimorfismo
  • Subclase

7. Literatura & Enlaces

[1]: Twenty C# Questions Explained - http://www.microsoftvirtualacademy.com
[2]: Miembros Función Virtuales en C# | OrtizOL - Experiencias Construcción Software (xCSw) - http://ortizol.blogspot.com/2013/12/miembros-funcion-virtuales-en-c.html
[3]: Clases y Miembros Abstractos en C# | OrtizOL - Experiencias Construcción Software (xCSw) - http://ortizol.blogspot.com/2013/12/clases-y-miembros-abstractos-en-c.html
[4]: abstract (C# Reference) - http://msdn.microsoft.com/en-us/library/sf985hc5.aspx
[5]: virtual (C# Reference) - http://msdn.microsoft.com/en-us/library/9fkccyh4.aspx
[6]: Difference Between Virtual and Abstract - http://www.differencebetween.com/difference-between-virtual-and-vs-abstract/
[7]: c# - What is the difference between an abstract function and a virtual function? - Stack Overflow - http://stackoverflow.com/questions/391483/what-is-the-difference-between-an-abstract-function-and-a-virtual-function


S

4 comentarios:

Envíe sus comentarios, dudas, sugerencias, críticas. Gracias.