consulta sobre property

Iniciado por feedf, 29 Marzo 2017, 00:54 AM

0 Miembros y 1 Visitante están viendo este tema.

feedf

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

Código (vbnet) [Seleccionar]
public nombre as string

o usando

Código (vbnet) [Seleccionar]
property nombre as string

muchisimas gracias

Eleкtro

#1
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 -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í:
Código (vbnet) [Seleccionar]
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:
Código (vbnet) [Seleccionar]
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.
Código (vbnet) [Seleccionar]
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:
Código (vbnet) [Seleccionar]
Public Interface IMyInterface
   Public MyField As String
End Interface

Sin embargo, una propiedad sí:
Código (vbnet) [Seleccionar]
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í:

Código (vbnet) [Seleccionar]
<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:

Código (vbnet) [Seleccionar]
<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!








feedf

Muchisimas gracias por la respuesta quedo muy claro !!!!!!!!!!!!

feedf

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

Eleкtro

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:


Saludos!








feedf

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:


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

Eleкtro

#6
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:
Código (vbnet) [Seleccionar]
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!








Serapis

#7
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:
Código (vbnet) [Seleccionar]

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:
Código (vbnet) [Seleccionar]

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.
Código (vbnet) [Seleccionar]

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.

Eleкtro

#8
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:




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:

Código (vbnet) [Seleccionar]
<Category("Appearance")>
<Description("The background color of the control.")>
<Localizable(True)>
Public Property BackColor As Color



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!