Solo quiero saber si hay alguien que pueda
explicarme sencillamente el concepto de modulos de clase,
y si no es mucha molestia mostrarme un ejemplo.
Gracias.
EDUARDO OLAZ
============
Un módulo de clase es un tipo de módulo de código, con el que se pueden
crear objetos que luego se pueden utilizar.
El módulo de clase en realidad es una estructura que puede almacenar datos
(Propiedades o atributos) y procedimientos sub y funciones (Métodos).
En un módulo de clase también se pueden definir eventos que generará la
clase cuando suceda lo que el programador determine.
El módulo de clase en realidad es algo así como los planos y el libro de
instrucciones de un objeto.
Es decir, la clase define cómo va a ser y cómo se va a comportar el objeto.
El objeto no existe hasta que la clase lo crea.
El objeto se crea cuando se realiza una "Instancia del mismo".
Por ejemplo si tenemos el módulo de clase con el nombre clsMiClase, para
usarla desde otra parte del código podemos escribir
Dim mcObjeto1 as clsMiClase
Con esto hemos reservado una zona de memoria para poder usar la clase
clsMiClase
El objeto no existe todavía; mcObjeto1 es una variable que "apuntará" al
objeto cuando realmente se cree.
para crearlo (crear la instancia del objeto) haremos
Set mcObjeto1 = new clsMiClase
En este momento, ya existe el objeto.
Se puede declarar y crear el objeto de forma simultánea.
Supongamos que tenemos definida la clase clsCuentaBancaria
Si hacemos
Dim cbCuenta_001 as new clsCuentaBancaria
Dim cbCuenta_002 as new clsCuentaBancaria
Dim cbCuenta_003 as new clsCuentaBancaria
Hemos creado tres objetos del tipo clsCuentaBancaria (instancias de
clsCuentaBancaria)
Si la, clase clsCuentaBancaria tiene las propiedades Titular y
NumeroDeCuenta, de escritura y lectura, podremos hacer:
cbCuenta_001.Titular = "Pepe Camuñas"
cbCuenta_001.NumeroDeCuenta = "00000001"
cbCuenta_002.Titular = "Pepa Araujo"
cbCuenta_002.NumeroDeCuenta = "00000002"
cbCuenta_003.Titular = "Lorenzo Parra"
cbCuenta_003.NumeroDeCuenta = "00000003"
Si por ejemplo la clase clsCuentaBancaria tuviera definido el procedimiento
(Método) GrabarDatos,
cbCuenta_001.Grabardatos
cbCuenta_002.Grabardatos
cbCuenta_003.Grabardatos
actualizarán los datos de las respectivas cuentas en las tablas
correspondientes.
Al final conviene destruir los objetos. por ejemplo así
set cbCuenta_001= nothing
set cbCuenta_002= nothing
set cbCuenta_003= nothing
Si tuviéramos, por ejemplo la clase clsMiClase, en la que hayamos definido
eventos, para poder interceptar los eventos de la clase, al declararla hay
que usar WithEvents
Por ejemplo
Dim WithEvents mcMiMejorClase as clsMiClase
Y en otra parte del código escribiremos
Set mcMiMejorClase = New clsMiClase
Si se declara con eventos no se puede crear el a la vez que se declara la
variable objeto.
Por ejemplo:
Dim WithEvents mcMiMejorClase as New clsMiClase daría error.
Las Propiedades de la clase se definen mediante procedimientos Property, que
en realidad son Del Tipo Sub, el de escritura y del tipo Function el de
lectura.
La diferencia es que un procedimiento Property debe tener el mismo nombre
para el de lectura y Escritura, y el mismo tipo de parámetro.
Por ejemplo mediante el siguiente código:
Public Property Let ErrorSinNumeros(ByVal GenerarError As Boolean)
BlnErrorSinNumeros = GenerarError
End Property
Public Property Get ErrorSinNumeros() As Boolean
ErrorSinNumeros = BlnErrorSinNumeros
End Property
Declaramos la propiedad de la clase ErrorSinNumeros, que será del tipo
Boolean
Property Let ErrorSinNumeros permite asignar el valor a la variable Privada
BlnErrorSinNumeros, declarada a nivel del módulo de clase.
Lo de tener definidas las variables, que van a guardar las propiedades de la
clase, de forma privada es para poder utilizar una de las características
de las clases que es la Encapsulación. Con ello el usuario de la clase, para
poder asignar el valor a la variable, tendrá que utilizar el procedimiento
Property correspondiente, En este procedimiento podremos controlar si el
valor pasado como parámetro para la propiedad tiene un valor adecuado.
Por ejemplo, si tenemos definida la clase Curso, y en ella la propiedad
NumeroDeAlumnos, de tipo long, no tendría sentido permitir que se
introdujera un valor negativo, o el valor 12586987.
Cuando se define una clase es para utilizarla nosotros u otros programadores
en un programa concreto, e incluso para poder reutilizarla en sucesivos
programas.
La utilización de clases tiene la gran ventaja de que, si están bien
definidas, podemos facilitarnos la vida o la del programador que las
utilice, así como la posterior depuración o cambios en los programas.
En realidad continuamente estamos utilizando clases, por ejemplo el módulo
que está asociado a un formulario es un módulo de clase.
Aquí te incluyo una clase que adjunté el otro día en mi respuesta a una
pregunta de Mario Roman
Es una clase que permite extraer de forma sucesiva valores numéricos
aleatorios, sin que se repitan, como en el bingo
Si observas tenemos definidas en ella las siguientes propiedades públicas:
Numeros
NumeroInferior
NumeroSuperior
NumerosExtraidos
ReanudarTrasUltimo
ErrorSinNumeros
Siguiente
Tiene definidos los métodos públicos
Inicializar
Revolver
También tiene el evento EventoSorteo
que puede enviar un parámetro del tipo TEventoSorteo
Depende cuando se genere el evento el parámetro que enviará será
csEvtClaseCreada
csEvtSerieInicializada
csEvtSerieAleatorizada
csEvtCambiadoNumeros
csEvtExtraidoNumero
csEvtExtraidoUltimoNumero
csEvtNumerosAgotados
csEvtClaseTerminada
Cuando se inicializa la clase, por defecto asigna los siguientes valores a
las propiedades
ReanudarTrasUltimo = True
ErrorSinNumeros = False
NumeroInferior = 1
Numeros = 90
Estas propiedades podrían ser adecuadas para usarlas en un programa que
emulara un juego de Bingo, o de Loto.
Si pusiéramos
NumeroInferior = 1
Numeros = 40
Nos serviría para un programa de baraja Española
Si pusiéramos
NumeroInferior = 1
Numeros = 54
Nos serviría para un programa de pócker con 2 comodines
Si pusiéramos
NumeroInferior = 12763
Numeros = 1412
Nos serviría para un programa que efectuara sorteos con venta de boletos
numerados, en el que en rifas anteriores se hubieran vendido 12762 boletos,
y en ésta hemos vendido 1412.
Como ves, la misma clase sirve para diferentes tipos de programa, sin tener
que efectuar cambios en el código de la misma.
Aquí te incluyo el código.
____________________________________
Option Explicit
' Número a devolver cuando se terminen
' los número disponibles
Private Const conlongMinimo As Long = -2147483648#
' Tipos de evento
Public Enum TEventoSorteo
csEvtClaseCreada
csEvtSerieInicializada
csEvtSerieAleatorizada
csEvtCambiadoNumeros
csEvtExtraidoNumero
csEvtExtraidoUltimoNumero
csEvtNumerosAgotados
csEvtClaseTerminada
End Enum
' Tipos de errores
Public Enum TErrorSorteo
csErsRango = 19000
csErsElementos = 19010
csErsSinNumeros = 19020
End Enum
' Array con los números
Dim alngNumeros() As Long
' Valor inferior de los números
Dim lngNumeroInferior As Long
' Total de números a sortear
Dim lngNumeros As Long
' Total de números extraídos
Dim lngExtraidos As Long
' Generación automática Sí/No
' de una nueva serie de números
' al finalizar los números
Dim blnReanudar As Boolean
' Indica si se genera un error
' al finalizar los números
Dim BlnErrorSinNumeros As Boolean
' la clase genera el evento EventoSorteo
Event EventoSorteo(Evento As TEventoSorteo)
Private Sub Class_Initialize()
' Inicializa con números tipo al bingo
RaiseEvent EventoSorteo(csEvtClaseCreada)
ReanudarTrasUltimo = True
ErrorSinNumeros = False
NumeroInferior = 1
Numeros = 90
Inicializar
End Sub
Public Property Let Numeros(ByVal Elementos As Long)
' Define el total de números a sortear
Select Case Elementos
Case Is < 1
Err.Raise csErsElementos, _
"Clase sorteo", _
"Debe haber, al menos, un elemento"
Case Is <> lngNumeros
lngNumeros = Elementos
RaiseEvent EventoSorteo(csEvtCambiadoNumeros)
Inicializar
Case Else
End Select
End Property
Public Property Get Numeros() As Long
Numeros = lngNumeros
End Property
Public Property Let NumeroInferior(ByVal Numero As Long)
lngNumeroInferior = Numero
RaiseEvent EventoSorteo(csEvtCambiadoNumeros)
End Property
Public Property Get NumeroInferior() As Long
NumeroInferior = lngNumeroInferior
End Property
Public Property Get NumeroSuperior() As Long
NumeroSuperior = lngNumeroInferior + lngNumeros - 1
End Property
Public Property Get NumerosExtraidos() As Long
NumerosExtraidos = lngExtraidos
End Property
Public Property Let ReanudarTrasUltimo(ByVal Reanudar As Boolean)
blnReanudar = Reanudar
End Property
Public Property Get ReanudarTrasUltimo() As Boolean
ReanudarTrasUltimo = blnReanudar
End Property
Public Property Let ErrorSinNumeros(ByVal GenerarError As Boolean)
BlnErrorSinNumeros = GenerarError
End Property
Public Property Get ErrorSinNumeros() As Boolean
ErrorSinNumeros = BlnErrorSinNumeros
End Property
Public Property Get Siguiente() As Long
lngExtraidos = lngExtraidos + 1
' Si ya se habían extraído todos los números
If lngExtraidos > lngNumeros Then
RaiseEvent EventoSorteo(csEvtNumerosAgotados)
' Si hemos definido que se repita el proceso
If blnReanudar Then
Inicializar
Siguiente = Siguiente()
' Si no se debe repetir el proceso
Else
' Si debemos generar el error
If BlnErrorSinNumeros Then
Err.Raise csErsSinNumeros, _
"Clase sorteo", _
"Los números se han agotado"
End If
' Se ha sobrepasado los números a extraer
' sin generar error
' Corregimos los números extraídos
lngExtraidos = lngExtraidos - 1
' Para mostrar la anomalía
' devolvemos el Long más bajo posible
Siguiente = conlongMinimo
End If
Exit Property
End If
Siguiente = alngNumeros(lngExtraidos)
If lngExtraidos < lngNumeros Then
RaiseEvent EventoSorteo(csEvtExtraidoNumero)
Else
RaiseEvent EventoSorteo(csEvtExtraidoUltimoNumero)
End If
End Property
Public Sub Inicializar()
Dim i As Long
Dim j As Long
lngExtraidos = 0
ReDim alngNumeros(1 To lngNumeros)
Randomize Timer
For i = 1 To lngNumeros
alngNumeros(i) = lngNumeroInferior + i - 1
Next i
' Revolvemos los números
Revolver
' Generamos el evento para indicar
' que la serie se ha inicializado
RaiseEvent EventoSorteo(csEvtSerieInicializada)
End Sub
Private Sub Class_Terminate()
' Eliminamos el array dinámico
Erase alngNumeros
RaiseEvent EventoSorteo(csEvtClaseTerminada)
End Sub
Public Sub Revolver()
Dim i As Long
Dim j As Long
lngExtraidos = 0
For i = 1 To lngNumeros
j = Int(Rnd * lngNumeros) + 1
Intercambia alngNumeros(i), alngNumeros(j)
Next i
RaiseEvent EventoSorteo(csEvtSerieAleatorizada)
End Sub
Private Sub Intercambia( _
ByRef Numero1 As Long, _
ByRef Numero2 As Long)
Dim lngIntermedio As Long
lngIntermedio = Numero1
Numero1 = Numero2
Numero2 = lngIntermedio
End Sub
____________________________________
Saludos desde la calle Estafeta de Pamplona
Eduardo Olaz
[Microsoft Access MVP]
eduardo@olaz.net
               (
geocities.com/es/ensolva/Descargas)                   (
geocities.com/es/ensolva)                   (
geocities.com/es)