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











    Source: geocities.com/es/ensolva/Descargas/Documentos

               ( geocities.com/es/ensolva/Descargas)                   ( geocities.com/es/ensolva)                   ( geocities.com/es)