Muchos lenguajes de programación orientado a objetos acceden a sus atributos a través de métodos. Esto lo vimos en el concepto anterior cuando accedíamos al atributo monto de un cliente:
Public Sub Depositar(ByVal m As Integer) monto = monto + m End Sub Public Function RetornarMonto() As Integer Return monto End Function
Vimos que luego llamamos a dichos métodos con la sintaxis:
cliente3.Depositar(200) cliente3.Extraer(150)
En Visual Basic .Net normalmente este tipo de problemas se lo resuelve implementado una propiedad. Veamos el mismo problemas resolviéndolo utilizando propiedades.
El problema era : Un banco tiene 3 clientes que pueden hacer depósitos y extracciones. También el banco requiere que al final del día calcule la cantidad de dinero que hay depositada.
Module Module1 Class Cliente Private _nombre As String Private _monto As Integer Public Property nombre() As String Get Return _nombre End Get Set(ByVal value As String) _nombre = value End Set End Property Public Property monto() As Integer Get Return _monto End Get Set(ByVal value As Integer) _monto = value End Set End Property Public Sub Imprimir() Console.WriteLine(nombre & " tiene depositado la suma de " & monto) End Sub End Class Public Class Banco Private cliente1, cliente2, cliente3 As Cliente Public Sub New() cliente1 = New Cliente() cliente1.nombre = "Juan" cliente1.monto = 0 cliente2 = New Cliente() cliente2.nombre = "Ana" cliente2.monto = 0 cliente3 = New Cliente() cliente3.nombre = "Pedro" cliente3.monto = 0 End Sub Public Sub Operar() cliente1.monto = cliente1.monto + 100 cliente2.monto = cliente2.monto + 150 cliente3.monto = cliente3.monto + 200 End Sub Public Sub DepositosTotales() Dim t As Integer = cliente1.monto + cliente2.monto + cliente3.monto Console.WriteLine("El total de dinero en el banco es:" & t) cliente1.Imprimir() cliente2.Imprimir() cliente3.Imprimir() End Sub End Class Sub Main() Dim banco1 = New Banco() banco1.Operar() banco1.DepositosTotales() Console.ReadKey() End Sub End Module
Lo más importante es entender que una propiedad es una forma de acceder al contenido de un atributo, tanto para consultar su valor como modificarlo.
Class Cliente Private _nombre As String Private _monto As Integer Public Property nombre() As String Get Return _nombre End Get Set(ByVal value As String) _nombre = value End Set End Property Public Property monto() As Integer Get Return _monto End Get Set(ByVal value As Integer) _monto = value End Set End Property
Los atributos los llamamos _nombre y _monto. Las propiedades las llamamos nombre y monto. Las propiedades no almacenan valores sino que normalmente acceden a los atributos para modificarlos o consultarlos.
La propiedad Nombre mediante el modificador set inicializa el atributo _nombre con el valor que llega del objeto:
cliente1.nombre = "Juan"
Como vemos donde definimos el objeto cliente1 accedemos a la propiedad mediante el operador punto y le asignamos un valor (en este caso un String porque la propiedad es de tipo String)
Si queremos consultar el atributo nombre lo podemos hacer mediante la propiedad Nombre. Es común definir el nombre que le damos al atributo con el mismo nombre que tiene la propiedad pero agregando el caracter _:
'atributo _monto Private _monto As Integer 'propiedad monto Public Property monto() As Integer Get 'valor devuelto por la propiedad Return _monto End Get Set(ByVal value As Integer) 'value indica el valor que se le asigna a la propiedad _monto = value End Set End Property
Podemos observar que la sintaxis para acceder a las propiedades donde definimos objetos es mucho mas intuitiva y sencillas, por ejemplo para saber cuanto dinero hay en el banco la sintaxis con propiedades es:
Dim t As Integer = cliente1.monto + cliente2.monto + cliente3.monto
Y como la vimos anteriormente por medio de un método que retorna el monto tenemos la siguiente sintaxis:
Dim t As Integer = cliente1.RetornarMonto() + cliente2.RetornarMonto() + cliente3.RetornarMonto()
Lo primero que nos viene a la mente es porque no definir los atributos con el modificador Public :
Public _monto as Integer
Para luego poder consultarlos y/o modificarlos con la sintaxis:
dim t as Integer = cliente1._monto + cliente2._monto + cliente3._monto
Ahora veamos que cuando consultamos o inicializamos una propiedad en realidad lo que está sucediendo es la ejecución de un método (Set o Get) donde podemos disponer código donde validar el valor asignado. Por ejemplo si disponemos la restricción que el Monto siempre debe ser positivo para que se almacene, luego debemos codificar la propiedad con la siguiente sintaxis:
Public Property monto() As Integer Get Return _monto End Get Set(ByVal value As Integer) If (value > 0) Then _monto = value Else Console.WriteLine("No se puede tener un monto negativo.") End If End Set End Property
Es decir si el valor que le asignamos a la propiedad Monto es negativo luego no se inicializa el atributo _monto con dicho valor.
Si ejecutamos este código luego debe mostrar un mensaje indicando que "No se puede tener monto negativo":
cliente1.Monto = -100
Plantear un programa que permita jugar a los dados. Las reglas de juego son: se tiran tres dados si los tres salen con el mismo valor mostrar un mensaje que "gano", sino "perdió".
Module Module1 Public Class Dado Private _valor As Integer Public Property valor() As Integer Get Return _valor End Get Private Set(value As Integer) _valor = value End Set End Property Private Shared aleatorio As Random Public Sub New() aleatorio = New Random() End Sub Public Sub Tirar() valor = aleatorio.Next(1, 7) End Sub Public Sub Imprimir() Console.WriteLine("El valor del dado es:" & valor) End Sub End Class Public Class JuegoDeDados Private dado1, dado2, dado3 As Dado Public Sub New() dado1 = New Dado() dado2 = New Dado() dado3 = New Dado() End Sub Public Sub Jugar() dado1.Tirar() dado1.Imprimir() dado2.Tirar() dado2.Imprimir() dado3.Tirar() dado3.Imprimir() If dado1.valor = dado2.valor And dado1.valor = dado3.valor Then Console.WriteLine("Ganó") Else Console.WriteLine("Perdió") End If Console.ReadKey() End Sub End Class Sub Main() Dim j = New JuegoDeDados() j.Jugar() End Sub End Module
El atributo _valor se lo accede por medio de la propiedad valor:
Private _valor As Integer Public Property valor() As Integer Get Return _valor End Get Set(value As Integer) _valor = value End Set End Property
Luego cuando queremos consultar el valor del dado desde el jugo de dados por medio de la sintaxis siguiente podemos comparar si los tres dados tienen el mismo número:
If dado1.valor = dado2.valor And dado1.valor = dado3.valor Then Console.WriteLine("Ganó") Else Console.WriteLine("Perdió") End If
Algo importante es poder restringir la ejecución del set o get desde fuera de la clase, por ejemplo en este caso queremos evitar que desde la clase JuegoDeDados se puede cambiar el valor del dado con la siguiente sintaxis:
dado1.Valor=7
La línea anterior provocará un error ya que sección del set de la propiedad la hemos definido de tipo Private (con esto hacemos que solo los métodos de la clase puedan ejecuta el Set). La sintaxis para acceder a la propiedad Valor desde la clase es:
Public Sub Tirar() valor = aleatorio.Next(1, 7) End Sub
Esto es correcto ya que el método Tirar pertenece a la clase Dado y por lo tanto puede asignarle un dato a la propiedad valor (cuando se asigna un valor a una propiedad se ejecuta el Set)
En las últimas versiones de Visual Studio .Net podemos generar el código fuente de una propiedad en forma automática, para ello disponemos el cursor sobre el atributo de la clase y seleccionamos del lado izquierdo la opción:
Luego de esto tenemos generado en forma automática el código fuente de la definición de la propiedad:
Podemos luego modificar el código generado y agregar validaciones por ejemplo.
Module Module1 Public Class Socio Private _nombre As String Private _antiguedad As Integer Public Property Nombre() As String Set(ByVal value As String) _nombre = value End Set Get Return _nombre End Get End Property Public Property Antiguedad() As Integer Set(ByVal value As Integer) If value >= 0 Then _antiguedad = value Else Console.Write("No se puede asignar aun valor negativo a la antiguedad") End If End Set Get Return _antiguedad End Get End Property End Class Public Class Club Private socio1, socio2, socio3 As Socio Public Sub New() socio1 = New Socio() socio1.Nombre = "Juan" socio1.Antiguedad = 7 socio2 = New Socio() socio2.Nombre = "Ana" socio2.Antiguedad = 3 socio3 = New Socio() socio3.Nombre = "Martin" socio3.Antiguedad = 25 End Sub Public Sub MayorAntiguedad() If socio1.Antiguedad > socio2.Antiguedad And socio1.Antiguedad > socio3.Antiguedad Then Console.WriteLine("Socio com mayor antiguedad:" & socio1.Nombre) Else If socio2.Antiguedad > socio3.Antiguedad Then Console.WriteLine("Socio com mayor antiguedad:" & socio2.Nombre) Else Console.WriteLine("Socio com mayor antiguedad:" & socio3.Nombre) End If End If End Sub End Class Sub Main() Dim club1 As New Club() club1.MayorAntiguedad() Console.ReadKey() End Sub End Module