miércoles, 29 de enero de 2014

Clases y Funciones Selladas en C#

Tabla de Contenido

0. Introducción
1. Clases Selladas
2. Funciones Selladas
3. Ventajas de Usar Elementos Sellados
Conclusiones
Glosario
Literatura & Literatura

0. Introducción

En este artículo les hablaré de otro de los puntos importantes acerca de la protección de tipos por medio de la construcción sintáctica sealed. Con esta construcción establecemos límites de herencia de los tipos que integran nuestro modelo del mundo del problema.

1. Clases Selladas

A través de una clase sellada restringimos el ámbito de herencia de un tipo de dato del modelo del mundo del problema. A través de esta restricción el programador está explicitando el bloqueo sobre la herencia de nuevos tipos de objeto que intenten heredar la funcionalidad y comportamiento del supertipo (es claro que ya no cabe este adjetivo para el tipo de dato en cuestión). En otros lenguajes de programación, por ejemplo en Java, se utiliza la construcción sintáctica final [4] para significar el mismo concepto de sellamiento (sí así se puede referenciar). Mientras que en Visual Basic NotInheritable [5].

La especificación para establecer el sellado de una clase en C# comprende el siguiente uso de sintaxis, es a través de la palabra clave sealed [1]. Véamos:



En [2] nos recuerdan acerca de que por defecto las estructuras vienen selladas por defecto. Y desde luego, no podemos hacer herencia en una clase desde una estructura.

1.1 Restricciones Inmediatas

El compilador de C# nos notificará a través de un error cuando intentemos heredar de una clase sellada. En el ejemplo que viene a continuacion se presenta el intento de heredar de una clase sellada y el error que nos arroja el compilador con este intento.

Archivo IntentoHerencia.cs

Prueba de ejecución.

Este es es el mensaje de error que nos arroja el compilador:

error CS0509: `NuevaClase': cannot derive from sealed type `ClaseSellada'

1.2 Rendimiento

De acuerdo con [7], las clases selladas ganan rendimiento sobre la máquina virtual de C#. Debido a que los tipos definidos como tal no requieren conocer tipos derivados en tiempo de ejecución.

2. Funciones Selladas

sealed también puede ser aplicado a funciones (e.g. métodos, propiedades). Por ejemplo, un método sellado (sealed, en inglés) consiste en una implementación final o definitiva que no puede ser modificada por los subtipos que hereden de una clase no sellada.

En [1] nos presentan un ejemplo muy interesante que consiste en el uso de sealed para prevenir que una subclase sobreescriba métodos virtuales o propiedaes.

Archivo MetodoSellado.cs:



En la clase ClaseA se declaran los métodos virtuales F y F2. Estos métodos son sobreescritos en la clase ClaseB; sólo el método F es sellado con el modificador sealed. Este método no podrá ser sobreescrito en subclases de la clase ClaseB. Esa es la tentativa en la subclase ClaseC.

> Prueba de ejecución.

3. Ventajas de Usar Clases y Funciones Sellados

Extraigo literalmente las consideraciones hechas sobre el porqué utilizar clases selladas encontradas en [3]:
Sometimes classes are too precious and not designed to be inherited.
Runtime/Reflection can make inheritance assumptions about sealed classes when looking for types. A great example of this is - Attributes are recommended to be sealed for lookup runtime speed. type.GetCustomAttributes(typeof(MyAttribute)) will perform significantly faster if MyAttribute is sealed.
En la sección 1.2 también se comento acerco de la ganancia de rendimiento con el uso de clases selladas.

También en [8] se citan ejemplos de nombres de espacio que contienen tipos de datos sellados: Pen [9] es una clase sellada que define métodos para dibujar líneas y curvas. Ahora, podemos asumir que se trata de tareas concretamente definidas que no requieren ser especializadas (máximo grado de especialización de un tipo). También, encontramos a la clase Brush [10], que posee características similares.

Conclusiones

Hemos aprendido cómo podemos definir una clase sellada, al igual que métodos sellados. También comprendimos su utilidad en la sección 3. Con este concepto, ya contamos con la herramienta básica para crear librerías con límites (bounderies) bien definidos.

En [11] podemos encontrar un test de rendimiento sobre tipos sellados y normales.

Glosario

- CLR
- Librería
- Sellado

Enlaces & Literatura

[1]: sealed (C# Reference) - http://msdn.microsoft.com/en-us/library/88c54tsw.aspx
[2]: Sealed Class in C# - http://www.c-sharpcorner.com/UploadFile/mahesh/SealedClasses11142005063733AM/SealedClasses.aspx?MessageChildID=1118&Delete=true
[3]: .net - Why seal a class? - Stack Overflow: - http://stackoverflow.com/questions/268251/why-seal-a-class
[4]: What is final in Java? Final variable , Method and Class Example - http://javarevisited.blogspot.com/2011/12/final-variable-method-class-java.html
[5]: NotInheritable (Visual Basic) - http://msdn.microsoft.com/en-us/library/h278d2d4.aspx
[6]: C# 5.0 in a Nutshell by Joseph Albahari and Ben Albahari. Copyright 2012 Joseph Albahari and Ben Albahari, 978-1-449-32010-2.
[7]: Sealed Classes And Methods In C# - C# Help | C# Help - http://www.csharphelp.com/2006/04/sealed-classes-and-methods-in-c/
[8]: What is the use of Sealed Classes in C#: C#, C / C++ / C# IDEs - http://www.experts-exchange.com/Programming/Editors_IDEs/Q_24030663.html
[9]: Pen Class (System.Drawing) - http://msdn.microsoft.com/en-us/library/system.drawing.pen%28v=vs.110%29.aspx#United%20States%20%28English%29
[10]: Brush Class (System.Drawing) - http://msdn.microsoft.com/en-us/library/system.drawing.brush(v=vs.110).aspx
[11]: C# Sealed Keyword - http://www.dotnetperls.com/sealed



H

sábado, 25 de enero de 2014

Ocultación de Miembros Heredados en C#

Tabla de Contenido

0. Introducción
1. Ocultación de Miembros Heredados
1.1 Construcción new (desambiguación: modificador)
1.2 Privatización de un miembro oculto
2. Ejemplo de Ocultación de Campo Miembro
3. new versus override
4. Conclusiones
5. Glosario
6. Enlaces & Literatura

0. Introducción

Casi por completar el mes sin una mínima actividad en el blog, reanudo mi proceso de escritura de artículos, recetas, ejercicios, aplicaciones, &c.

En esta oportunidad les hablaré acerca de la ocultación de miembros en C#. Ocurre con frecuencia mientras que heredamos miembros de un tipo sobre otro. Esta ocultación tiene un semejante cuando en un método eclipsa las campos de instancia por medio de las variables o parámetros declarados en la firma o en la implementación del método. Haré algunas demostraciones por medio de algunos ejemplos sencillos de herencia, y el uso de construcciones del lenguaje para alcanzar este comportamiento.

1. Ocultación de Miembros Heredados

En C# podemos ocultar miembros (funciones: métodos, propiedades, indezadores, eventos; y campos) a través de construcciones del lenguaje. Exactamente por medio de la palabra clave new [5]. En los ejemplos próximos, veremos que la ausencia de esta construcción, hace que el compilador arrojará una advertencia sobre el uso no adecuado y consciente de la ocultación del miembro heredado.

1.1 Construcción new (desambiguación: modificador)

Cuando usamos new en la definición de la firma de un método estamos explicitando que éste último va a ocultar la definición de la clase base. Vayamos con un par de ejemplos en donde se omite el uso de new, y en otro en donde se incluye.

En este primer ejemplo se omite el uso de la palabra clave new sobre la definición del método en la clase base:

Archivo OmisionNew.cs:



Cuando ponemos a prueba este archivo obtenemos:

► Prueba de ejecución.

El compilador arrojará la siguiente advertencia:

warning CS0108: 'ClaseDerivada.F()' hides inherited member 'ClaseBase.F()'. Use the new keyword if hiding was intended.

En este ejemplo se incluye la versión con el modificador new:

Archivo InclusionNew.cs:



Vemos que para explicitar la ocultación imponemos el modificar new en la misma firma del método F.

1.2 Privatización de un miembro oculto

Por privatización en este contexto, entiéndase el efecto de marcar como private y al mismo tiempo ocultar el miembro por medio de new en el subtipo. Para que quede más claro, echemos un vistazo al siguiente ejemplo (reusaré la versión de la sección 1.1).

Archivo PrivatizacionMiembroHeredado.cs:

En la línea 7 se declara como private el método heredado F (ya oculto a través de new). Cuando en la línea 12 la clase NuevaClase hereda de ClaseDerivada, se ha definido un método homónimo, el cual en su implementación invoca al método F; aquí hay que tener en cuenta que como en ClaseDerivada privatizamos este método, en este caso se invocará la versión declarada en ClaseBase.


1.3 Nota acerca del uso ambiguo de new

En [1] nos advierten sobre la ambigüedad de la construcción de C# new:
Ambigüedad new
Figura 1. Ambigüedad new [1].

2. Ejemplo de Ocultación de Campo Miembro

Este ejemplo demuestra la ocultación de un campo de instancia. Vayamos directo al ejemplo:

Archivo OcultacionCampo.cs:

No se espeficó el modificador new para ocultar de forma explícita y evitar que el compilador arroje la advertencia de ocultamiento no intencionado.

La modificación para el siguiente ejemplo, consiste en inclusión del modificador new para ocultar explícitamente el campo de instancia Counter.

Archivo OcultacionCampoNew.cs:



3. new versus override

Consideremos el siguiente ejemplo (adaptado de [1])  para demostrar la diferencia en el uso de estos dos construcciones.

Archivo DiferenciaNewOverride.cs:



> Prueba de ejecución.

Como se demuestra en la ejecución de prueba, con override [6] se sobreescribe completamente, y al mismo tiempo se toma posesión del control del método MetodoPrueba en la clase derivada. Esto se evidencia en la invocación b1.MetodoPrueba() (b1 es de tipo ClaseBase pero referencia un objeto de tipo Overrider).

Por otro lado, cuando usamos new no tomamos posesión del método MetodoPrueba en la invocación desde la sentencia b2.MetodoPrueba(). Aquí b2 es de tipo ClaseBase pero referencia a un objeto de tipo Hider; sin embargo, se invoca la versión de la primera, es decir, de ClaseBase.

[Nota: Para mayor información acerca de las diferencias diríjase a [7]].

Conclusiones

Comprendimos el mecanismo de ocultación de miembros de superclases a través del uso del modificador new. Reconocimos que la ausencia de este modificador hace que el compilador advierta sobre el uso no consentido de ocultación de miembro. Apreciamos a través de ejemplos cómo usar el modificador para métodos y campos de instancia (secciones 1.1 y 2). Finalmente, la diferencia entre new y override.

Glosario

- Ocultación
- Sobrescritura

Enlaces & Literatura

[1]: C# 5.0 in a Nutshell by Joseph Albahari and Ben Albahari. Copyright 2012 Joseph Albahari and Ben Albahari, 978-1-449-32010-2. 
[2]: 3.7.1.2 Hiding through inheritance (C#) - http://msdn.microsoft.com/en-us/library/aa691135(v=vs.71).aspx 
[3]: Polymorphism, Method Hiding and Overriding in C# - http://www.akadia.com/services/dotnet_polymorphism.html 
[4]: Method Hiding in C# - CodeProject - http://www.codeproject.com/Articles/18733/Method-Hiding-in-C 
[5]: new Modifier (C# Reference) - http://msdn.microsoft.com/en-us/library/435f1dw2.aspx
[6]: Knowing When to Use Override and New Keywords (C# Programming Guide) - http://msdn.microsoft.com/en-us/library/ms173153.aspx 
[7]: override (C# Reference) - http://msdn.microsoft.com/en-us/library/ebca9ah3.aspx


H