Propiedades
Propiedades
¿Que son las propiedades?
En los ejemplos anteriores vimos una clase llamada horse, la cual tenia varios campos, nombre, color y altura. En el constructor buscábamos que la altura estuviera dentro del rango de entre 1 y 2.5 metros. Esto nos aseguraba de que fuera que el objeto tuviera valores reales. Pero, aun asi, el usuario podia tener acceso directamente al valor dentro de la clase m_height.
Dim h as horse = New horse (“Bucefalo”, “black”, 2)
h._mheight = -250.34
Si el usario le cambia la altura al caballo a valores negativos entonces, ya tendríamos un objeto no valido. Se dice de un objeto invalido que tiene un estado inconsistente, significa que tiene valores que no coinciden o valores incorrectos entre los campos de la clase (miembros de los datos).
El caso aquí es que, si usamos el campo como publico (m_height) para representar la un atributo altura en la clase, el usuario de la clase puede inadvertidamente cambiarlo a un valor invalido. Podemos limitar el acceso al campo haciendolo Friend, y solamente el código del ensamble puede dañar la clase. Pero entonces nadie fuera del entorno podría saber cual es la altura del caballo. Esta es una limitacion severa en la funcionabilidad. Para solucionar este tipo de problema, se introdujo las propiedades de la clase.
De un punto de vista conceptual, los campos y las propiedades son similares: Ambos son utilizados para implementar el valor de un atributo de la clase. Hemos visto que los los campos son solamente variables que retienen datos. Las propiedades son una forma de procedimiento que te permite ajustar y la manera en como se comportara un atributo dentro de una clase. Normalmente utiliza un campo private o protected.
Public Class Horse
Public m_name As String
Public m_color As String
Private m_height As Single = 1.5
Public Property altura() As Single
Get
Return m_height
End Get
Set(ByVal Value As Single)
If 1 <= Value And Value <= 2.5 Then
m_height = Value
End If
End Set
End Property
Public Sub New(ByVal name As String, ByVal color As String, ByVal height As Single)
m_name = name
m_color = color
MyClass.altura = height
End Sub
End Class
La primera cosa que hay que observar es que m_height es ahora privado; puede ser accedida desde el miembro de la clase, pero será invisible para cualquiera fuera de la clase.
Hemos agregado el enunciado Property el cual es muy similar a un enunciado de una funcion. Tiene un tipo, el cual nos indica el tipo de propiedad. En este caso la propiedad es Single. El enunciado de la Propiedad se compone de dos partes (bloque y enunciados): un bloque GET y otro bloque SET. Por lo menos uno de los dos bloques debe de estar presente. Veremos cual de los dos puede ser omitido.
El bloque GET es el que es ejecutado cuando el usuario accesa la propiedad. Esto es conocido como bloque de lectura. El bloque es delimitado por GET y el enunciado END GET. Este bloque puede contener cualquier enunciado regular y debe terminar regresando el valor de la propiedad. El valor que regresa debe coincidir con el tipo de la propiedad. En este caso regresamos el valor del campo privado m_height.
El bloque SET, es usado para cambiar el valor de la propiedad. Esto pasa cuando un usuario intenta cambiar el valor. Se ejecuta cuando el usuario intente cambiar este valor. Se espera que el valor se guarde en algún lugar (por ejemplo en un campo privado) y cuando se lea después, se regrese. Como el bloque GET, el Bloque SET esta delimitado por las palabras SET y END SET. Dentro del bloque, podemos tener enunciados regulares. Normalmente tenemos código que verifica que el valor cambiado por el usuario sea valido. Es importante que entendamos que este valor es del mismo valor que el del tipo de la propiedad (single) y que esta representado por la palabra Value. Esta palabra no esta declarada por ningún lado, y debe de ser accedida dentro del bloque SET. Dentro de nuestro ejemplo vimos que verificamos que el valor se encuentra dentro de los rangos para la altura de un caballo,.
Usando Propiedades
Las propiedades pueden ser usadas exactamente como los campos son usados. Por ejemplo, si usamos la clase que ya hemos definido antes, podemos escribir el siguiente código:
Dim caballo As Horse
caballo = New Horse("Caballito", "Blanco", 2.2)
Console.WriteLine("Nombre: {0}", caballo.m_name)
Console.WriteLine("Color: {0}", caballo.m_color)
Console.WriteLine("Tamaño: {0}", caballo.altura)
Las propiedades son muy útiles si tenemos una propiedad que es solo-lectura o algunas veces solo-escritura. Algunas veces querremos prevenir que los usuarios cambien directamente una propiedad. Si tenemos una clase llamada persona esto modela una persona con un nombre y una fecha de nacimiento, podríamos elegir en inicializar el nombre de la persona y la fecha de nacimiento y hasta crear un nuevo objeto y no permitir al usuario cambiarlos después. Esto puede ser posible usando una propiedad de solo lectura. Esta es una propiedad que los usuarios pueden leer (get) pero no cambiar:
Public Class Person
Private m_name As String
Private m_dob As Date
Public ReadOnly Property name() As String
Get
Return m_name
End Get
End Property
Public ReadOnly Property dob() As Date
Get
Return m_dob
End Get
End Property
Public Sub New(ByVal name As String, ByVal dob As Date)
m_name = name
m_dob = dob
End Sub
End Class
Ambas propiedades de esta clase usan el modificador de solo-lectura que indican que solo hay un bloque GET definido- que esta propiedad no puede ser cambiada (SET).
El ejemplo del modulo es el siguiente:
Module Module1
Sub Main()
Dim p As Person
p = New Person("Daniel", #7/4/1972#)
Console.WriteLine("Nombre: {0} Fecha: {1}", p.name, p.dob)
Console.ReadLine()
End Sub
End Module
Si el usuario escribiera el siguiente código p.name = “Ragnar D.” Esto no se compilaria. Esto es un mecanismo empleado en el encapsulamiento (protección) de datos para las instancias de una clase.
Puedes usar propiedades de solo-escritura usando el modificador WriteOnly para la propiedad del bloque SET. Esto forzará a la propiedad de solo aceptar asignaciones, pero no permitirá lecturas, es el opuesto de una propiedad ReadOnly. WriteOnly es utilizado solo algunas veces y normalmente para datos volatiles (por ejemplo en el flujo de datos, como en la salida a la consola) Por ejemplo:
Public Class OutTextStream
Public WriteOnly Property outText() As String
Set(ByVal Value As String)
Console.WriteLine(Value)
End Set
End Property
End Class
Module Module1
Sub Main()
Dim o As OutTextStream
o = New OutTextStream
o.outText = "Esto es la salida"
Console.ReadLine()
End Sub
End Module
Creamos una clase que nos permite tener salida de texto hacia la consola cambiando el valor de una propiedad llamada outText. En esta ocasión no hay ningún campo en donde guardar datos, asi que no tiene sentido tener un GET, que regresaríamos?
Bibliografia VB .NET by Example p .258-263