Historia de la pregunta
Las propiedades en Visual Basic permiten encapsular la lógica para obtener y asignar valores. Con la introducción de propiedades, el código se vuelve más legible y seguro, eliminando la necesidad de acceso directo a los campos de la clase y facilitando la implementación de la lógica de validación o cálculos directamente en los objetos.
Problema
A menudo, los novatos hacen que un campo sea público o utilizan propiedades automáticas sin getters/setters que contengan lógica, lo que lleva a una violación de la encapsulación o a la imposibilidad de implementar valores calculados. Otro problema es la llamada recursiva a la propiedad dentro de sí misma, lo que conduce a un StackOverflow.
Solución
En Visual Basic, se declara un campo privado y la propiedad incluye bloques Get y Set con la lógica necesaria. Las propiedades calculadas utilizan solo Get, devolviendo un valor calculado basado en los campos privados. Dentro del bloque set, siempre se debe hacer referencia al campo privado para evitar la recursión infinita.
Ejemplo de código:
Private _price As Decimal Private _quantity As Integer Public Property Total As Decimal Get Return _price * _quantity ' propiedad calculada End Get End Property Public Property Price As Decimal Get Return _price End Get Set(value As Decimal) If value < 0 Then Throw New ArgumentException("El precio debe ser positivo") _price = value End Set End Property
Características clave:
¿Se puede hacer referencia a la propiedad Name dentro de Set Price, si también está implementada a través de un campo privado?
Sí, si en el bloque set de la propiedad Price se hace referencia a otra propiedad (por ejemplo, Name), esto es permitido, ya que las referencias a diferentes campos privados no provocan recursión. Se debe evitar hacer referencia a sí mismo: llamar a Price dentro de Set Price provocará recursión.
Ejemplo de código:
Public Property Name As String Get Return _name End Get Set(value As String) _name = value End Set End Property Public Property Price As Decimal Get Return _price End Get Set(value As Decimal) If Name Is Nothing Then _name = "default" _price = value End Set End Property
¿Qué sucederá si dentro del bloque Get de la propiedad se llama a esta propiedad nuevamente?
Esto llevará a una recursión infinita y a un StackOverflow. En el bloque get, siempre utilice el campo privado; de lo contrario, la propiedad se llamará a sí misma.
Public Property Amount As Decimal Get Return Amount ' conducirá a recursión infinita End Get Set(value As Decimal) _amount = value End Set End Property
¿Se puede declarar una propiedad de solo escritura (WriteOnly) y cuán peligrosa es?
Existen propiedades WriteOnly, pero no se recomienda su uso, ya que el objeto pierde la capacidad de devolver un valor, lo que perjudica la legibilidad y previsibilidad. Si solo se necesita para escribir, es mejor revisar la arquitectura.
Private _secret As String Public WriteOnly Property Secret As String Set(value As String) _secret = value ' Se puede escribir, no se puede obtener. End Set End Property
Un programador decidió hacer público el campo Price y trabajó directamente con él. Como resultado, Price a veces se volvía negativo por error.
Ventajas:
Desventajas:
Un colega reemplazó Price por una propiedad con un campo privado y validación en el bloque set, lo que previno valores incorrectos.
Ventajas:
Desventajas: