martes, 6 de abril de 2010

Tutorial sobre los módulos de clase

1 - Introducción

Las propiedades y los métodos de una clase forman la interfaz predeterminada de dicha clase. La interfaz predeterminada es la manera más habitual de manipular los objetos.
En general, las propiedades representan datos de un objeto, mientras que los métodos representan acciones que un objeto puede realizar. Para expresarlo de otro modo, las propiedades proporcionan la descripción de un objeto y los métodos su comportamiento.
Los temas siguientes describen los mecanismos para agregar propiedades y métodos a las clases y tratan algunos de los problemas que se va a encontrar.
Agregar propiedades a una clase Describe las dos maneras de agregar propiedades a las clases: la manera fácil y la correcta.
Procedimientos Property frente a variables públicas Aunque los procedimientos de propiedad son la mejor manera de implementar la mayoría de las propiedades, las variables públicas tienen su utilidad.
Poner los procedimientos de propiedad en funcionamiento
Proporciona detalles completos acerca del funcionamiento de los procedimientos de propiedad y describe la implementación de los tipos de propiedad más comunes.
Por ejemplo, sólo lectura, lectura y escritura, objeto y Variant. 
Agregar métodos a una clase Los métodos (el comportamiento de un objeto) son simples procedimientos públicos que puede agregar a un módulo de clase.
¿Es una propiedad o un método? Algunas veces no es obvio si la funcionalidad deseada se debe implementar como propiedad o como método. Este tema proporciona algunas recomendaciones.
Crear una propiedad o un método predeterminados Puede utilizar el cuadro de diálogo Atributos del procedimiento para asignar a una clase un miembro predeterminado.
Propiedades y métodos Friend Los procedimientos Friend se encuentran a mitad de camino entre los Public y los Private. Al igual que estos últimos, no forman parte de la interfaz de una clase y, al igual que los Public, son visibles desde cualquier parte del proyecto. Se pueden utilizar para pasar tipos definidos por el usuario.
Nota Los eventos no forman parte de la interfaz predeterminada. Los eventos son interfaces salientes (es decir, interfaces que afectan a otros objetos), mientras que las propiedades y los métodos pertenecen a las interfaces entrantes (es decir, las interfaces cuyos miembros se invocan desde otros objetos). La interfaz predeterminada de un objeto de Visual Basic es una interfaz entrante.
Importante Los siguientes nombres no pueden utilizarse como nombres de propiedades o de métodos, ya que pertenecen a las interfaces subyacentes IUnknown e IDispatch:
QueryInterface, AddRef, Release, GetTypeInfoCount, GetTypeInfo, GetIDsOfNames e Invoke. Estos nombres producirán un error de compilación.
Para obtener más información Los eventos se describen en “Agregar eventos a una clase”, más adelante en este tema.


2 - Agregar propiedades a una clase

La forma más sencilla de definir las propiedades de una clase es agregar variables públicas al módulo de clase. Por ejemplo, puede crear de forma sencilla una clase Account si declara dos variables públicas en un módulo de clase llamado Account:
Public Balance As Double
Public Name As String
Es muy fácil. Tanto como crear los datos privados de una clase; simplemente declare una variable Private y sólo será accesible desde el código del módulo de clase:
Private mstrMothersMaidenName As String
Private
mintWithdrawalsMonthToDate As Integer

Ocultar datos
La capacidad de proteger parte de los datos de un objeto a la vez que se expone el resto como propiedades se llama ocultación de los datos. Éste es un aspecto del principio de encapsulamiento orientado a objetos, como se explica en “Clases: combinación de tipos definidos por el usuario y procedimientos”.
Ocultar los datos significa que puede efectuar modificaciones en la implementación de una clase sin afectar al código existente que utilice el objeto Account, por ejemplo mediante el cambio de Integer a Long de la variable privada de la clase Account mintWithdrawalsMonthToDate.
Ocultar los datos también le permite definir propiedades de sólo lectura. Por ejemplo, puede utilizar un procedimiento Property Get para obtener el valor de la variable privada que contiene el número de retiradas de efectivo del mes e incrementar sólo la variable desde el código del objeto Account. Lo que nos lleva a los procedimientos de propiedad.
Procedimientos de propiedad
Ocultar los datos no tendría utilidad si la única forma de crear propiedades fuera la declaración de variables públicas. ¿De qué sirve dar una propiedad Type a la clase Account, si cualquier código que tenga una referencia de un objeto Account puede establecer alegremente el tipo de cuenta a cualquier valor?
Los procedimientos de propiedad le permiten ejecutar código cuando se establece o se obtiene el valor de una propiedad. Por ejemplo, podría implementar la propiedad Type del objeto Account como una pareja de
procedimientos de propiedad:
Public Enum AccountTypes
 atSavings = 1
 atChecking
 atLineOfCredit
End Enum
  
' Almacenamiento de datos privado de la propiedad Type.
Private matType As AccountTypes
 
Public Property Get Type() As AccountTypes
 Type = matType
End Property
 
Public Property Let Type(ByVal NewType As AccountTypes)
 Select Case NewType
  Case atChecking, atSavings, atLineOfCredit
   ' No hace nada si NewType es válido.
  Case Else
   Err.Raise Number:=vbObjectError + 32112, _
   Description:="Tipo de cuenta no válido"
 End Select
 If mbytType > NewType Then
  Err.Raise Number:=vbObjectError + 32113, _
  Description:="Imposible actualizar el tipo de 
  cuenta"
 Else
  mbytType = NewType
 End If
End Property

Ahora suponga que tiene una variable llamada acct que contiene una referencia a un objeto Account. Cuando se ejecuta el código x = acct.Type, se invoca el procedimiento Property Get para devolver el valor almacenado en el miembro de datos privado mbytType del módulo de clase.
Cuando se ejecuta el código acct.Type = atChecking se invoca el procedimiento Property Let. Si el objeto Account es nuevo, mbytType será cero y se le puede asignar cualquier tipo válido de cuenta. Si el tipo actual de cuenta es atSavings, se actualizará la cuenta.
Sin embargo, si el tipo actual de cuenta es atLineOfCredit, Property Let producirá un error que evita la actualización. De igual forma, si se ejecuta el código acct.Type = 0, la instrucción Select del procedimiento Property Let detectará un tipo de cuenta no válido y producirá un error.
En resumen, los procedimientos de propiedad permiten que un objeto proteja y valide sus propios datos.
Para obtener más información Entonces, ¿para qué sirven las variables públicas? En “Procedimientos de propiedad frente a variables públicas” se explican los usos apropiados de cada uno.
Las posibilidades de los procedimientos de propiedad se exploran con más detalle en “Poner en funcionamiento los procedimientos de propiedad”.


3 - Procedimientos de propiedad frente a variables públicas

Los procedimientos de propiedad son un medio tan poderoso de encapsulamientos que quizás se esté preguntando si alguna vez va a trabajar con variables públicas. La respuesta, como siempre en programación, es “Por supuesto, algunas veces”. He aquí algunas reglas básicas:
Utilice procedimientos de propiedad cuando:
  • La propiedad es de sólo lectura o no se puede modificar después de establecerla.
  • La propiedad tiene un conjunto de valores bien definido que es necesario validar.
  • Los valores fuera de un determinado intervalo (por ejemplo, números negativos) son válidos para el tipo de datos de la propiedad, pero provocarían errores de programa si se permite que la propiedad asuma dichos valores.
  • Establecer la propiedad provoca algún cambio perceptible en el estado del objeto, por ejemplo una propiedad Visible.
  • Establecer la propiedad provoca cambios en otras variables internas o en los valores de otras propiedades.
Utilice variables públicas en las propiedades de lectura y escritura cuando
  • La propiedad es de un tipo autovalidable. Por ejemplo, si a una variable booleana se le asigna un valor distinto de True o False, se produce un error o una conversión automática de datos.
  • Es válido cualquier valor del intervalo aceptado por el tipo de datos.
    Esto se dará en muchas propiedades de tipo Single o Double.
  • La propiedad es del tipo de datos String y no hay limitaciones en el tamaño o el valor de la cadena.
Nota No implemente una propiedad como variable pública solamente por evitar el costo de una llamada de función. Internamente, Visual Basic implementará de todos modos las variables públicas de los módulos de clase como parejas de procedimientos de propiedad, ya que esto es lo requerido por la biblioteca de tipos.
Para obtener más información Las capacidades de los procedimientos de propiedad se explican con más detalle en “Poner en funcionamiento los procedimientos de propiedad”.


4 - Poner en funcionamiento los procedimientos de propiedad

Visual Basic proporciona tres tipos de procedimientos de propiedad, que se describen en la tabla siguiente.
Procedimiento Propósito
Property Get Devuelve el valor de una propiedad.
Property Let Establece el valor de una propiedad.
Property Set Establece el valor de una propiedad de objeto (es decir, una propiedad
que contiene una referencia a un objeto).

Como puede ver en la tabla, cada uno de estos procedimientos de propiedad desempeña un papel concreto en la definición de una propiedad. La propiedad típica estará compuesta por una pareja de procedimientos de propiedad: Property Get para obtener el valor de la propiedad y Property Let o Property Set para asignar un nuevo valor.
Estos papeles se pueden superponer en algunos casos. La razón por la que hay dos tipos de procedimientos de propiedad para asignar un valor es que Visual Basic tiene una sintaxis especial para la asignación de referencias de objeto a las variables de objeto:
Dim wdg As Widget
Set wdg = New Widget

La regla es sencilla: Visual Basic llama a Property Set si se utiliza la instrucción Set y a Property Let en caso contrario.
Sugerencia Para distinguir entre Property Let y Property Set, recuerde los lenguajes Basic antiguos, cuando en vez de x = 4 tenía que escribir Let x = 4 (sintaxis aceptada por Visual Basic hasta hoy en día). Visual Basic siempre llama al procedimiento de propiedad que corresponde al tipo de asignación: Property Let para Let x = 4 y Property Set para Set c1 = New Class1 (es decir, para las propiedades de objeto).
Para obtener más información En el tema “Trabajar con objetos” de “Fundamentos de programación” explica el uso de la instrucción Set con las variables de objeto.

Propiedades de lectura y escritura
El siguiente fragmento de código muestra una típica propiedad de lectura y escritura:
' Almacenamiento privado del valor de la propiedad.
Private mintNumberOfTeeth As Integer
 
Public Property Get NumberOfTeeth() As Integer
 NumberOfTeeth = mintNumberOfTeeth
End Property
 
Public Property Let NumberOfTeeth(ByVal NewValue _
 As Integer)
 ' (Se omite el código para validar la propiedad.)
 mintNumberOfTeeth = NewValue
End Property
 

El nombre de la variable privada que almacena el valor de la propiedad está compuesto por un prefijo de alcance (m) que la identifica como variable de nivel de módulo, un prefijo de tipo (int) y un nombre (NumberOfTeeth). Utilizar el mismo nombre que para la propiedad sirve para recordar que la variable y la propiedad están relacionadas.
Como sin duda habrá observado, en este ejemplo y en los anteriores los nombres de los procedimientos de propiedad que forman una propiedad de lectura y escritura tienen que ser iguales.
Nota Los procedimientos de propiedad son públicos de forma predeterminada, de modo que si se omite la palabra clave Public, seguirán siendo públicos. Si por alguna razón quiere que una propiedad sea privada (es decir, sólo accesible desde dentro del objeto), tiene que declararla con la palabra clave Private. Lo correcto es utilizar la palabra clave Public, aunque no se requiera, ya que deja claras sus intenciones.
Procedimientos de propiedad como trabajo y como diversión
Es instructivo recorrer el código de algún procedimiento de propiedad. Abra un nuevo proyecto Exe estándar y agregue un módulo de clase mediante el menú Proyecto. Copie el código de la propiedad NumberOfTeeth, mostrado anteriormente, a Class1.
Cambie a Form1 y agregue el siguiente código al evento Load:
Private Sub Form_Load()
 Dim c1 As Class1
 Set c1 = New Class1
 ' Asigna un nuevo valor a la propiedad.
 c1.NumberOfTeeth = 42
 ' Presenta el valor de la propiedad.
 MsgBox c1.NumberOfTeeth
End Sub 
Presione F8 para recorrer el código de línea en línea. Observe que cuando se asigna el valor a la propiedad, pasa al procedimiento Property Let y que cuando lo obtiene, pasa a Property Get. Puede que encuentre útil repetir este ejercicio con otras combinaciones de procedimientos de propiedad.

Los argumentos de las parejas de procedimientos de propiedad tienen que coincidir
Los ejemplos de procedimientos de propiedad vistos hasta ahora eran sencillos, como lo son para la mayoría de las propiedades. Sin embargo, los procedimientos de propiedad pueden tener múltiples argumentos e incluso argumentos opcionales. Los múltiples argumentos son útiles en las propiedades que actúan como matrices, como se describe a continuación.
Cuando utilice argumentos tienen que coincidir los argumentos de cada pareja de procedimientos de propiedad. La tabla siguiente muestra los argumentos requeridos en las declaraciones de los procedimientos de propiedad.
Procedimiento Sintaxis de la declaración
Property Get Property Get propiedad(1,..., n) As tipo
Property Let Property Let propiedad(1,..., n, n+1)
Property Set Property Set propiedad(1,..., n, n+1)

Desde el primer argumento al último (1,..., n), todos deben compartir los mismos nombres y tipos de datos en los procedimientos de propiedad con el mismo nombre. Como en otros tipos de procedimientos, todos los parámetros requeridos de esta lista tienen que preceder al primer parámetro opcional.
Probablemente habrá advertido que la declaración del procedimiento Property Get tiene un argumento menos que los de Property Let o Property Set relacionados. El tipo de datos del procedimiento Property Get tiene que ser igual que el tipo de datos del último argumento (n+1) de los Property Let o Property Set relacionados.
Por ejemplo, considere esta declaración de Property Let para una propiedad que actúa como matriz de dos dimensiones:
Public Property Let Things(ByVal X As Integer, _
ByVal Y As Integer, ByVal Thing As Variant)
 ' (Se omite el código para asignar el elemento 
 '  de la matriz.)
End Property 

La declaración de Property Get tiene que utilizar argumentos con el mismo nombre y el mismo tipo de datos que los argumentos del procedimiento Property Let:
Public Property Let Things(ByVal X As Integer, _
ByVal Y As Integer) As Variant
 ' (Se omite el código para leer la matriz.)
End Property 
El tipo de datos del último argumento de una declaración Property Set tiene que ser un tipo de objeto o una variable Variant.

Coincidencia de los argumentos
La razón de estas reglas de coincidencia de los argumentos se ilustra en la figura 9.8, que muestra cómo Visual Basic asocia las partes de la instrucción de asignación con los argumentos de un procedimiento Property Let.

El uso más común de los procedimientos de propiedad con varios argumentos es el de crear matrices de propiedades.
Propiedades de sólo lectura
Para crear una propiedad de sólo lectura, simplemente omita el procedimiento Property Let o (para las propiedades de objeto) el procedimiento Property Set.
Propiedades de objeto
Si va a crear una propiedad de objeto de lectura y escritura, utilice un Property Get y un Property Set, como se muestra a continuación:
Private mwdgWidget As Widget
 
Public Property Get Widget() As Widget
 ' La instrucción Set se debe utilizar para 
 ' obtener una referencia de objeto.
 Set Widget = mwdgWidget
End Property
 
Public Property Set Widget(ByVal NewWidget As Widget)
 Set mwdgWidget = NewWidget
End Property

Propiedades Variant
Las propiedades de lectura y escritura del tipo de datos Variant son las más complicadas. Utilizan los tres tipos de procedimientos de propiedad, como se muestra a continuación:
Private mvntAnything As Variant
 
Public Property Get Anything() As Variant
 ' La instrucción Set sólo se utiliza cuando la 
 ' propiedad Anything contiene una referencia de 
 ' objeto.
 If IsObject(mvntAnything) Then
  Set Anything = mvntAnything
 Else
  Anything = mvntAnything
 End If
End Property
 
Public Property Let Anything(ByVal NewValue As Variant)
 ' (Se omite el código de validación.)
 mvntAnything = NewWidget
End Property
 
Public Property Set Anything(ByVal NewValue As Variant)
 ' (Se omite el código de validación.)
 Set mvntAnything = NewWidget
End Property
 

Los procedimientos Property Set y Property Let no tienen dificultad, puesto que siempre se les llama en las circunstancias correctas. Sin embargo, Property Get tiene que controlar los dos casos siguientes:
strSomeString = objvar1.Anything
Set objvar2 = objvar1.Anything

En el primer caso, la propiedad Anything contiene una cadena, que se asigna a una variable String. En el segundo caso, Anything contiene una referencia de objeto, que se asigna a una variable de objeto.
Puede escribir código para el procedimiento Property Get de forma que controle estos dos casos, mediante el uso de la función IsObject, que comprueba la variable Variant privada antes de devolver el valor.
Naturalmente, si se llama a la primera línea de código cuando Anything contiene una referencia de objeto, se produce un error, pero eso no es un problema de Property Get, sino un problema derivado del uso de las propiedades Variant.

Propiedades de una única escritura
Hay muchas combinaciones posibles de procedimientos de propiedad. Todas ellas son válidas, pero algunas son relativamente poco frecuentes, como las propiedades de sólo escritura (sólo Property Let, sin un Property Get). Además, algunas dependen de factores distintos que los tipos de procedimientos de propiedad que combine.
Por ejemplo, cuando organiza los objetos de su programa con la creación de un modelo de objetos, como se describe en “Modelos de objetos”, más adelante en este tema, puede desear que un objeto sea capaz de devolver una referencia al objeto que lo contiene. Puede hacer esto si implementa una propiedad Parent.
Tiene que establecer esta propiedad Parent cuando se crea el objeto, pero a partir de ese momento quizás desee impedir su modificación, ya sea de forma accidental o intencionada. En el ejemplo siguiente se muestra cómo el objeto Account puede implementar una propiedad Parent que apunte al objeto Department que contiene la cuenta.
' Almacenamiento de datos privado de la propiedad 
' Parent.
Private mdeptParent As Department
 
Property Get Parent() As Department
 ' Instrucción Set para devolver 
 ' referencias de objeto.
 Set Parent = mdeptParent
End Property
 
' El valor de la propiedad sólo se puede 
' establecer una vez.
Public Property Set Parent(ByVal NewParent _
As Department)
 If deptParent Is Nothing Then
  ' Asigna el valor inicial.
  Set mdeptParent = NewParent
 Else
  Err.Raise Number:=vbObjectError + 32144, _
  Description:="La propiedad Parent es de sólo lectura"
 End If
End Property

Cuando tiene acceso al objeto primario de un objeto Account, por ejemplo con el código strX = acctNew.Parent.Name para obtener el nombre del departamento, se invoca Property Get para devolver la referencia al objeto primario.
El procedimiento Property Set de este ejemplo se ha escrito para que la propiedad Parent sólo se establezca una vez. Por ejemplo, cuando el objeto Department crea una nueva cuenta, puede ejecutar el código Set acctNew.Parent = Me para establecer la propiedad. Posteriormente, la propiedad es de sólo lectura.
Para obtener más información Puesto que los formularios de Visual Basic son clases, puede agregar propiedades personalizadas a los formularios. Consulte “Personalización de las clases Form”, anteriormente en este tema.


5 - Agregar métodos a una clase

Los métodos de una clase son como los procedimientos Sub o Function públicos que suele declarar. Como los procedimientos Sub y Function son públicos de forma predeterminada, ni siquiera tiene que especificar explícitamente la palabra clave Public al crear un método.
Por ejemplo, para crear un método Withdrawal para la clase Account puede agregar este procedimiento Public Function al módulo de clase:
Public Function WithDrawal(ByVal Amount As Currency, _
ByVal TransactionCode As Byte) As Double
 ' (Código para realizar el cobro y devolver el 
 ' nuevo saldo o un error.)
End Function
 

Sugerencia Aunque no es necesario escribir la palabra clave Public, es conveniente hacerlo puesto que deja claras sus intenciones a otras personas que vayan a mantener el código en el futuro.

Declaración de métodos como procedimientos Public Sub
La devolución del nuevo saldo es opcional, ya que podría llamar fácilmente a la propiedad Balance del objeto Account después de llamar al método Withdrawal. Por tanto, podría escribir el método Withdrawal como procedimiento Public Sub.
Sugerencia Si siempre tiene que llamar a Balance después de llamar a Withdrawal, la devolución del nuevo saldo sería más eficiente. Esto se debe a que, como puede ver en “Agregar propiedades a módulos de clase”, el acceso a cualquier propiedad, incluso la lectura de una variable pública, significa una llamada a una función; es decir, un Property Get explícito o implícito.

Importante Los siguientes nombres no pueden utilizarse como nombres de propiedades o de métodos, ya que pertenecen a las interfaces subyacentes IUnknown e IDispatch: QueryInterface, AddRef, Release, GetTypeInfoCount, GetTypeInfo, GetIDsOfNames e Invoke. Estos nombres producirán un error de compilación.
Para obtener más información Para obtener más información sobre procedimientos Sub y Function, vea “Introducción a los procedimientos”, en “Fundamentos de programación”.

Protección de los detalles de implementación
La interfaz pública de una clase se define mediante las declaraciones de las propiedades y los métodos del módulo de clase. Como en la ocultación de los datos, los procedimientos declarados como Private no forman parte de la interfaz. Esto quiere decir que puede realizar modificaciones en los procedimientos internos de un módulo de clase sin afectar al código que utiliza los objetos.
Y más importante aún, también puede modificar el código de los procedimientos públicos Sub o Function que implementa un método sin afectar al código que utiliza el método. Mientras no modifique los tipos de datos de los argumentos del procedimiento o el tipo de datos devuelto por un procedimiento Function, la interfaz no se altera.
La ocultación de los detalles de la implementación de un objeto detrás de su interfaz es otra faceta del encapsulamiento. El encapsulamiento le permite mejorar el rendimiento de los métodos o modificar completamente la implementación de un método sin tener que modificar el código que utiliza dicho método.
Nota Las recomendaciones de nomenclatura de los elementos de la interfaz (descritos en “Nombres de propiedades, métodos y eventos”) no sólo se aplican a los nombres de las propiedades y de los métodos, sino también a los nombres de los parámetros de los procedimientos Sub y Function que definen los métodos. Estos nombres de parámetros son visibles cuando ve los métodos en el Examinador de objetos y puede utilizarlos como parámetros con nombre (es decir, parámetro:=valor) al invocar los métodos.
Para obtener más información Los argumentos con nombre se describen en “Pasar argumentos a procedimientos”, en “Fundamentos de programación”.
Agregar métodos a las clases formulario es una eficaz técnica de programación, que se describe en “Personalización de las clases Form”.
Algunas veces no está muy claro si un miembro debe ser una propiedad o un método. “¿Es una propiedad o un método?” le ofrece algunas recomendaciones.

6 - ¿ Es una propiedad o un método ?

En general, una propiedad es un dato sobre un objeto, mientras que un método es una acción que puede pedir que realice el objeto. Algunos elementos son obviamente propiedades, como Color y Name, y algunas son obviamente métodos, como Move y Show.
Sin embargo, como en cualquier otra faceta del comportamiento humano, hay un terreno de nadie en el que un argumento puede ser cualquiera de los dos.
Por ejemplo, ¿por qué el método Item de la clase Collection de Visual Basic es un método y no una propiedad indizada? ¿No son datos los elementos de una colección? El método Item de una supuesta clase de colección Widgets podría implementarse de cualquiera de las dos maneras, como se muestra a continuación:
' Almacenamiento privado para los objetos de la colección 
' Widgets (el mismo para ambas implementaciones).
Private mcol As New Collection
 
Public Property Get Item(Index As Variant) As Widget
 Set Item = mcol.Item(Index)
End Function
 
- o bien -
 
Public Function Item(Index As Variant) As Widget
 Set Item = mcol.Item(Index)
End Function

No hay una gran diferencia entre estas dos implementaciones. Las dos son de sólo lectura, de modo que ambas dependen del método Add de la clase Widgets para insertar objetos Widget en la colección. Las dos delegan todo en un objeto Collection, incluso sus errores los genera el objeto Collection.
Para obtener más información La delegación se explica en “Múltiples facetas (e interfaces) de la reutilización del código” y en “Creación de sus propias clases de colección”, más adelante en este tema.
Puede que nunca termine de decidir si un miembro es un dato sobre el objeto o un comportamiento del objeto. Por ejemplo, puede argumentar que Item es un método porque la colección realiza una tarea que le ha pedido: busca el Widget que desea. Sin embargo, este razonamiento también es válido para explicar lo contrario.
Puede encontrar más útil dejar dar la vuelta al argumento y preguntarse cómo quiere definir el miembro. Si quiere que la gente piense que es un dato del objeto, haga que sea una propiedad. Si quiere que piensen que es una acción que puede efectuar el objeto, haga que sea un método.

El argumento de la sintaxis
Una razón de peso para implementar un miembro mediante procedimientos de propiedad depende de la manera en que quiere utilizar el miembro desde el código. Es decir, ¿podrá el usuario de una colección Widgets escribir el código siguiente?
Set Widgets.Item(4) = wdgMyNewWidget
Si se le permite, implemente el miembro como propiedad de lectura y escritura, mediante Property Get y Property Set, puesto que los métodos no aceptan esta sintaxis.
Nota En la mayoría de las implementaciones de colecciones con las que encontrará, no se permite esta sintaxis. La implementación de un procedimiento Property Set en una colección no es tan fácil como parece.

El argumento de la ventana Propiedades
También puede suponer por un momento que el objeto es como un control. ¿Puede imaginarse al miembro visible en la ventana Propiedades o en una página de propiedades? Si no lo ve claro, no implemente el miembro como una propiedad.
El argumento del error sensible
Si olvida que hizo de Item una propiedad de sólo lectura e intenta asignarle un valor, entenderá más fácilmente el mensaje de error que Visual Basic provoca en Property Get (“Imposible asignar la propiedad de sólo lectura”) que el mensaje de error que provoca en un procedimiento Function (“La llamada a Function en la parte izquierda de la asignación debe devolver un tipo Variant u Object”).
El argumento del último recurso
Como último recurso, tire una moneda al aire. Si ninguno de los argumentos de este tema le parece convincente, es que probablemente no hay una gran diferencia.
Para obtener más información Los procedimientos de propiedad se presentan en “Agregar propiedades a las clases”, anteriormente en este tema. Los métodos se describen en “Agregar métodos a las clases”.


7 - Creación de una propiedad o método predeterminado


Puede asignar propiedades predeterminadas a los objetos creados a partir de las clases, como las propiedades predeterminadas de los objetos proporcionados por Visual Basic. El mejor candidato para ser el miembro predeterminado es el que tenga un uso más frecuente.
Para establecer una propiedad o un método como predeterminado
1 En el menú Herramientas, seleccione Atributos del procedimiento para abrir el cuadro de diálogo Atributos del procedimiento.
2 Haga clic en Avanzadas para expandir el cuadro de diálogo Atributos del procedimiento.
3 En el cuadro Nombre, seleccione la propiedad o el método que es actualmente el predeterminado de la clase. Si la clase no tiene actualmente un miembro predeterminado, pase al punto 5.
Nota Puede utilizar el Examinador de objetos para buscar el miembro predeterminado actual de una clase. Cuando selecciona la clase en la lista Clases, puede desplazarse por los miembros de la lista Miembros; el miembro predeterminado estará marcado con un pequeño círculo azul al lado del icono.
4 En el cuadro Id. del procedimiento, seleccione Ninguno para quitar el estado predeterminado de la propiedad o del método.
5 En el cuadro Nombre, seleccione la propiedad o el método que quiera que sea el nuevo miembro predeterminado.
6 En el cuadro Id. del procedimiento, seleccione (Predeterminado); después haga clic en Aceptar.
Importante Una clase sólo puede tener un miembro predeterminado. Si una propiedad o un método ya está marcado como predeterminado, tiene que restablecer el Id. del procedimiento a Ninguno antes de hacer que otra propiedad o método sea el predeterminado. No se producen errores de compilación si dos miembros están marcados como predeterminados, pero es imposible predecir cuál es el que Visual Basic elegirá como predeterminado.
También puede abrir el cuadro de diálogo Atributos del procedimiento desde el Examinador de objetos. Esto es muy cómodo cuando va a modificar el miembro predeterminado de una clase, ya que le permite encontrar rápidamente el miembro predeterminado existente.
Para modificar una propiedad predeterminada mediante el Examinador de objetos
1 Presione F2 para abrir el Examinador de objetos.
2 En la lista Clases, seleccione la clase cuyo miembro predeterminado quiere modificar.
3 En la lista Miembros, haga clic con el botón secundario del mouse en el miembro que tiene un pequeño círculo azul al lado del icono para abrir el menú contextual. Haga clic en Propiedades para mostrar el cuadro de diálogo Atributos del procedimiento.
4 Haga clic en Avanzados para expandir el cuadro de diálogo Atributos del procedimiento.
5 En el cuadro Id. del procedimiento, seleccione (Ninguno) para quitar el estado predeterminado de la propiedad o del método; después haga clic en Aceptar.
6 En la lista Miembros, haga clic con el botón secundario en el miembro que quiere que sea el nuevo miembro predeterminado para abrir el menú contextual. Haga clic en Propiedades para mostrar el cuadro de diálogo Atributos del procedimiento.
7 Haga clic en Avanzados para expandir el cuadro de diálogo Atributos del procedimiento.
8 En el cuadro Id. del procedimiento, seleccione (Predeterminado); después haga clic en Aceptar.
Nota No puede utilizar el cuadro de diálogo Atributos del procedimiento para modificar el miembro predeterminado de una clase proporcionada por Visual Basic.


8 - Propiedades y métodos Friend

Además de declarar propiedades y métodos Public y Private, puede declararlos Friend. Los miembros Friend son como miembros Public para los demás objetos del proyecto. Es decir, parecen parte de la interfaz de una clase. Pero no lo son.
En los componentes ActiveX que puede crear con la Edición profesional y la Edición empresarial de Visual Basic, los miembros Friend desempeñan un papel importante. Como no forman parte de la interfaz de un objeto, no pueden tener acceso a ellos los programas que utilizan los objetos del componente. Sin embargo, son visibles para todos los demás objetos del componente, por lo que permiten una comunicación interna segura dentro del componente.
Importante Puesto que los miembros Friend no forman parte de la interfaz pública de un objeto, no se puede tener acceso a ellos con enlaces en tiempo de compilación; es decir, mediante variables declaradas As Object. Para utilizar miembros Friend tiene que declarar las variables con enlaces en tiempo de diseño; es decir, As clase.
Los proyectos Exe estándar no pueden ser componentes ActiveX, ya que sus módulos de clase no pueden ser Public y, por tanto, no los pueden utilizar otras aplicaciones. Toda la comunicación entre los objetos de un proyecto Exe estándar es privada y no necesita miembros Friend
Sin embargo, los miembros Friend tienen una característica especialmente útil. Como no forman parte de una interfaz ActiveX, se pueden utilizar para pasar tipos definidos por el usuario de un objeto a otro. Por ejemplo, suponga que tiene el siguiente tipo definido por el usuario en un módulo estándar:
Public Type udtDemo
 intA As Integer
 lngB As Long
 strC As String
End Type 

Puede definir la siguiente variable privada y los siguientes miembros Friend en Class1:
Private mDemo As udtDemo
 
Friend Property Get Demo() As udtDemo
 Demo = mDemo
End Property
 
 
' Observe que udtDemo tiene que pasarse por referencia.
Friend Property Let Demo(NewDemo As udtDemo)
 mDemo = NewDemo
End Property
 
Friend Sub SetDemoParts(ByVal A As Integer, _
  ByVal B As Long, ByVal C As String)
 mDemo.intA = A
 mDemo.lngB = B
 mDemo.strC = C
End Sub
 
Public Sub ShowDemo()
 MsgBox mDemo.intA & vbCrLf _
 & mDemo.lngB & vbCrLf & mDemo.strC
End Sub
 

Nota Cuando pasa tipos definidos por el usuario como argumentos de procedimientos Sub, Function o Property, tiene que pasarlos por referencia. (ByRef es el paso predeterminado de argumentos a los procedimientos.)
Por tanto, puede escribir el código siguiente para utilizar Class1:
Private Sub Command1_Click()
 Dim c1A As New Class1
 Dim c1B As New Class1
 c1A.SetDemoParts 42, 1138, "Hola"
 c1B.Demo = c1A.Demo
 c1B.ShowDemo
End Sub 

El cuadro de mensajes presentará 42, 1138 y “Hola”.
Nota Puesto que los procedimientos Friend no forman parte de la interfaz de una clase, no se incluyen cuando utiliza la instrucción Implements para implementar múltiples interfaces, como se describe en “Polimorfismo”.
Para obtener más información El uso de miembros Friend en los componentes se describe en el tema “Comunicación privada entre los objetos” de “Principios generales del diseño de componentes”, en la Guía de herramientas componentes.

No hay comentarios:

Publicar un comentario