Buenas como andan? estoy empezando en este mundillo les queria preguntar cual es la diferencia entre definir un atributo de un objeto usando por ejemplo
public nombre as string
o usando
property nombre as string
muchisimas gracias
Hola.
La diferencia principal y de forma resumida es que una variable es tan solo una variable, mientras que una propiedad es un miembro que encapsula dos métodos para proveer la funcionalidad de leer o escribir alrededor de una variable.
Primero hay que aclarar que si tomásemos el ejemplo que has puesto tal cual, de forma literal, entonces entre public nombre as string y property nombre as string no habría ninguna diferencia significativa que valiese la pena mencionar, puesto que más que de una propiedad estaríamos hablando de una propiedad auto-implementada: https://msdn.microsoft.com/en-us/library/dd293589.aspx (https://msdn.microsoft.com/en-us/library/dd293589.aspx) -es decir, un tipo de propiedad en la que Visual Studio se haria responsable de su implementación Get/Set y de la variable de apoyo (o backing field) de forma automática, privándonos así de poder controlar esas funcionalidades básicas de una propiedad.
Sin embargo, si modificásemos tu ejemplo para dejar la definición de una propiedad tal que así:
Public Property MyProperty As String
Get
Return Me.myBackingField
End Get
Set(ByVal value As String)
Me.myBackingField = value
End Set
End Property
Private myBackingField As String
...entonces ya habría una diferencia muy destacable. Por un lado tendriamos una simple variable, y ahora tendriamos una propiedad que encapsula dos métodos, Getter y Setter alrededor de esa variable, lo que nos permitiría imiplementar métodos de validación para obtener y/o asignar el valor de esa propiedad. La diferencia es muy grande, igual que el control y la responsabilidad que obtendriamos sobre el comportamiento de nuestro código.
A este punto cabe mencionar que podemos definir una popiedad en modo sólo-lectura:
Public ReadOnly Property MyProperty As String
Set(ByVal value As String)
Return Me.myBackingField
End Set
End Property
Private myBackingField As String
o en modo sólo-escritura, siendo esto último una diferencia imposible de reproducir en una variable.
Public WriteOnly Property MyProperty As String
Set(ByVal value As String)
Me.myBackingField = value
End Set
End Property
Private myBackingField As String
Otra diferencia muy importante entre una propiedad y un valor de campo o variable es el propósito de ambos tipos de miembros. Una variable por ejemplo no se puede declarar al definir una interfáz:
Public Interface IMyInterface
Public MyField As String
End Interface
Sin embargo, una propiedad sí:
Public Interface IMyInterface
Public Property MyProperty As String
End Interface
Y cuando estemos trabajando con una clase, una variable suele ser declarada con una visibilidad privada (o al menos así debería ser declarada) para impedir su acceso y/o su modificación desde otros niveles superiores de accesibilidad de clase, por otro lado una propiedad suele ser un miembro declarado con una visibildidad pública para exponer como ya hemos dicho un mecanismo de lectura y escritura alrededor de una variable (una variable con visibilidad privada).
Dentro del propósito de cada miembro entraríamos a mencionar las diferencias de representación que tienen cada uno de estos miembros en tiempo de diseño...
Tenemos por ejemplo una clase que hereda de la clase UserControl, nuestra intención es diseñar un control personalizado que cumpla "X" propósito y para ello queremos exponer un miembro público para que el usuario pueda modificar en tiempo de diseño el color del borde del control (por poner un ejemplo sencillo y aleatorio) mediante el diseñador o designer del control en Visual Studio. ¿Cómo lo hariamos?, pues muy necesariamente tendriamos que exponer esta funcionalidad a través de una propiedad (ya sea auto implementada o no) como por ejemplo así:
<DesignTimeVisible(True)>
<ToolboxItem(True)>
Public Class MyControl : Inherits UserControl
<Browsable(True)>
<Category("Appearance")>
Public Property BorderColor As Color
End Class
...Puesto que si intentásemos reproducir la misma funcionalidad con una variable entonces no se representaría ningún mecanismo de lectura y escritura en tiempo de diseño en el diseñafor del control, por lo que no serviría de nada usar una variable en un escenario como este:
<DesignTimeVisible(True)>
<ToolboxItem(True)>
Public Class MyControl : Inherits UserControl
<Browsable(True)>
<Category("Appearance")>
Public BorderColor As Color
End Class
Hay varias diferencias más, como por ejemplo la ventaja de poder hacer databinding gracias a una propiedad y no a una variable, o las diferencias de serialización entre cada tipo de miembro, pero bueno, creo haber explicado las diferencias más notables e importantes en el uso cotidiano que un programador común le suele dar a este tipo de miembros, y no quiero excederme demasiado más alargando este post.
PD: Todas estas reglas o diferencias que he mencionado se aplican también al lenguaje C#.
¡Saludos!
Muchisimas gracias por la respuesta quedo muy claro !!!!!!!!!!!!
Public Property MyProperty As String
Get
Return Me.myBackingField
End Get
Set(ByVal value As String)
Me.myBackingField = value
End Set
End Property
Private myBackingField As String
Te hago una pregunta que me surgio, osea que dentro del objeto creamos una variable privada para que no sea vista por todo el programa, pero la que interactua para leer y escribir en esa variable es la propiedad con los gets y los sets
conoces algun video que explique bien el tema y como usarla y implementarlas?
}
mil gracias
Cita de: feedf en 30 Marzo 2017, 00:40 AMconoces algun video que explique bien el tema y como usarla y implementarlas?
¿Video tutorial?, no, pero todo lo que necesitas saber se encuentra en la MSDN:
- Información general sobre propiedades (https://msdn.microsoft.com/es-es/library/65zdfbdt.aspx)
- Procedimientos de propiedad (https://msdn.microsoft.com/es-es/library/bc3dtbky.aspx)
- Cómo: Crear una propiedad (https://msdn.microsoft.com/es-es/library/e8ae41a4.aspx)
Saludos!
Cita de: Eleкtro en 30 Marzo 2017, 01:03 AM
¿Video tutorial?, no, pero todo lo que necesitas saber se encuentra en la MSDN:
- Información general sobre propiedades (https://msdn.microsoft.com/es-es/library/65zdfbdt.aspx)
- Procedimientos de propiedad (https://msdn.microsoft.com/es-es/library/bc3dtbky.aspx)
- Cómo: Crear una propiedad (https://msdn.microsoft.com/es-es/library/e8ae41a4.aspx)
Saludos!
y lo que habia puesto en mi post es correcto ?
" osea que dentro del objeto creamos una variable privada para que no sea vista por todo el programa, pero la que interactua para leer y escribir en esa variable es la propiedad con los gets y los sets"
gracias me ayudaste un monton :D
Cita de: feedf en 30 Marzo 2017, 01:06 AM" osea que dentro del objeto creamos una variable privada para que no sea vista por todo el programa, pero la que interactua para leer y escribir en esa variable es la propiedad con los gets y los sets"
Exacto.
Si tienes una propiedad con nombre "MiPropiedad" y un valor de apoyo o backing field con nombre "MiVariable", cuando tu haces esto:
Sub()...
MiPropiedad = Valor
End Sub
...El método Get de "MiPropiedad" se encarga de validar y asignar el valor a "MiVariable".
No le des demasiadas vueltas al tema, una propiedad la utilizarías practicamente de la misma manera que una variable (excepto por el Get y el Set, pero no te obsesiones con eso) y no importa demasiado si decides usar variables o propiedades ...excepto en casos específicos donde es recomendable (o es la única opción) el uso de propiedades.
Saludos!
Aparte de lo que te señala Electro, otra razón para usarla con Get y Set, es que tienes pleno control de su valor y de cuando esta cambia...
Por ejemplo si se pasa un valor que no aceptable:
Private p_Mes As byte
Public Property Mes As byte
Get
Return p_Mes
End Get
Set(ByVal value As byte)
If (value<12) then
p_mes = value
' else
' puedes por ejemplo informar al usuario que el valor no se admite que queda fuera de rango permitido...
end if
End Set
End Property
Otro ejemplo, saber cuando un valor cambia o cuando se recibe un valor específico:
Private p_Mes As byte
Public Property Mes As byte
Get
Return p_Mes
End Get
Set(ByVal value As byte)
If (value <> p_mes) then ' el valor es distinto al almacenado actualmente.
p_mes = value
RaiseEvent MesCambiado(p_mes) ' de este modo se podria informar a otro componente, por ejemplo a un calendario para que exhibiera el mes que ha introducido el usuario.
' O simplemente actualizar el nombre del mes en una caja de texto.
Textbox1.Text = Meses(p_mes) ' Meses seria aquí un array con los nombres de los meses...
end if
End Set
End Property
' Saber si ha cambiado, es importante... si hay que hacer mucha funcionalidad, y resulta que el valor recibido esel mismo que ya existe, podríamos omitir hacer todo ese trabajo, solo hacelro si ha cambiado (cuando es estrictamente necesario).
También puedes controlar cuantas veces permites que cambie un valor, si hubiera alguna ocasión en que esto deba ser restringido.
Private p_Contraseña As string
private s_Cambios as byte
Public Property Contraseña As string
Get
Return p_Contraseña
End Get
Set(ByVal value As string)
if (s_Cambios <3) then ' solo permite un máximo de 3 cambios...
If (value<>p_Contraseña) then
s_Cambios +=1
p_Contraseña = value
end if
else
' informar al usuario que ya se han hecho los 3 cambios de contraseña permitidos...
end if
End Set
End Property
Es decir, no solo se contenta uno con recibir y devolver un valor, la mayor ventaja es precisamente poder SABER más cosas acerca del valor que se recibe (también cuando se entrega, aunque no ponga un ejemplo explícito), y en base a ello hacer lo que proceda si es necesario. Y la posibilidad de hacer más cosas en base a ese SABER acerca del valor recibido/devuelto.
Cita de: NEBIRE en 30 Marzo 2017, 01:33 AMotra razón para usarla con Get y Set, es que tienes pleno control de su valor y de cuando esta cambia...
Es decir, no solo se contenta uno con recibir y devolver un valor, la mayor ventaja es precisamente poder SABER más cosas acerca del valor que se recibe (también cuando se entrega, aunque no ponga un ejemplo explícito), y en base a ello hacer lo que proceda si es necesario. Y la posibilidad de hacer más cosas en base a ese SABER acerca del valor recibido/devuelto.
Ya que estamos, otro ejemplo de notificación de cambios del valor de una propiedad sería mediante la implementación de la interfáz
INotifyPropertyChange:
- https://msdn.microsoft.com/en-us/library/ms229614(v=vs.100).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1 (https://msdn.microsoft.com/en-us/library/ms229614(v=vs.100).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1)
Otra ventaja bastante importante que no mencioné al utilizar propiedades, serïa la capacidad de utilizar classes de atributos específicos o compatibles para este tipo de miembros.
Los atributos son simples metadatos que podemos "adherir" a la definición de un miembro (en este caso a una propiedad) y que suelen modificar el comportamiento del código en tiempo de diseño.
Por ejemplo, al estar diseñando un control de usuario, un atributo muy usado para una propiedad sería el atributo "
<Category()>", con el que podemos hacer que nuestra propiedad se represente dentro de una categoría específica en la grilla de propiedades del control, o el atributo "
<Description()>" que nos permite presentar una descripción del propósito de nuestra propiedad en la grilla de propiedades del control:
<Category("Appearance")>
<Description("The background color of the control.")>
<Localizable(True)>
Public Property BackColor As Color
- https://msdn.microsoft.com/en-us/library/system.componentmodel.categoryattribute(v=vs.110).aspx (https://msdn.microsoft.com/en-us/library/system.componentmodel.categoryattribute(v=vs.110).aspx)
- https://msdn.microsoft.com/en-us/library/system.componentmodel.descriptionattribute(v=vs.110).aspx (https://msdn.microsoft.com/en-us/library/system.componentmodel.descriptionattribute(v=vs.110).aspx)
La propiedad
<Localizable(True)> se encargaría de traducir automáticamente el nombre "
Appearance" en la grilla de propiedades al idioma actual de Visual Studio y también la descripción aportada en el atributo
<Description()> siempre y cuando estos sean localizables, es decir que si usamos Visual Studio en Español entonces nuestra propiedad aparecería en la categoría "Apariencia" y su descripción sería la misma que usa Microsoft por defecto.
Existen muchos tipos de classes de atributos que son aplicables a distintos tipos de miembros (a classes, módulos, interfaces, propiedades, métodos y funciones, etc) y por supuesto NO todos ellos tienen un propósito estético, hay atributos para especificar un rango de valor mínimo y máximo para una propiedad, por ejemplo, o atributos para modificar el comportamiento del depurador de Visual Studio sobre un miembro específico.
¡Saludos!