home *** CD-ROM | disk | FTP | other *** search
-
-
-
-
-
-
-
-
-
-
-
- ╔═════════════════════════════════════════════════════════════════════╗
- ║ ║
- ║ XCLASS 2.00 ║
- ║ ║
- ║ Extensión a Clipper 5.01 para Programación Orientada al Objeto ║
- ║ ║
- ║ (c) 1993 Carlos Ruiz Ruiz ║
- ║ ║
- ╚═════════════════════════════════════════════════════════════════════╝
-
-
- Versión de Dominio Público
-
- Prohibida su Venta
-
-
-
- -pag. 2-
-
-
-
-
-
- INDICE
- ======
-
- CARACTERISTICAS...................................3
-
- AGRADECIMIENTOS...................................3
-
- INTRODUCCION A LA OOP.............................3
-
- GLOSARIO..........................................5
-
- SINTAXIS..........................................6
-
- SENTENCIAS, EXPRESIONES Y FUNCIONES...............7
- -CLASS.........................................7
- -VAR / DATA....................................7
- -RENAME VAR....................................7
- -DELETE VAR....................................8
- -MESSAGE.......................................8
- -MESSAGE METHOD................................8
- -MESSAGE BLOCK.................................9
- -MESSAGE VIRTUAL..............................10
- -CONSTRUCTOR METHOD...........................10
- -RENAME MESSAGE...............................11
- -DELETE MESSAGE...............................11
- -ENDCLASS.....................................12
- -METHOD.......................................12
- -PARENT.......................................12
- -SUPER........................................13
- -QSUPER.......................................13
- -CLASSH.......................................14
- -CLASSNAME....................................14
- FUNCIONES:
- -OCLONE.......................................14
- -NEWOBJECT....................................15
- -OSAVE........................................15
- -OLOAD........................................16
-
- PSEUDO-COMANDOS..................................16
-
- DEBUGGER.........................................16
-
- METODOS-PADRE....................................17
-
-
-
- -pag. 3-
-
-
- XClass es una extensión del compilador Clipper para Programación
- Orientada al Objeto. Está basado en las funciones internas no
- documentadas de la librería Clipper y sólo donde estas no llegan se ha
- hecho necesaria la programación adicional.
-
-
- CARACTERISTICAS
- ===============
- -Soporte de herencia múltiple y simple.
- -Soporte de métodos constructores.
- -Creación de clases en tiempo de ejecución.
- -Asociación de mensajes con métodos (funciones) o Code Blocks.
- -Mensajes virtuales.
- -Compatibilidad con el Debugger
- -Código eficiente y compacto.
- -Posibilidad de redefinición y borrado de mensajes y variables en
- clases derivadas.
- -Método rápido de acceso a los mensajes-padre.
- -Compatibilidad con una amplia variedad de sintaxis, especialmente con
- SuperClass 1.2
- -GRABACION y LECTURA en DISCO de cualquier OBJETO
- -Modularidad en el diseñó. Sólo se linkan aquellos módulos que son
- realmente utilizados.
-
-
- AGRADECIMIENTOS
- ===============
- XClass es el producto de un pequeño aporte del autor a otras grandes
- ideas que han servido de base, especialmente de:
- -Peter M. Freese, autor de oClip, primera librería de dominio público.
- -Chris Sennit, autor de SuperClass.
- -Antonio Linares, autor de ClassMaker, Dialog, Object... y esperemos
- que mucho más.
- -Francisco Pulpón, que aportó ideas muy buenas para mejorar las
- anteriores.
- -Antonio Rojo, autor de OopClip.
-
-
- INTRODUCCION
- ============
- ¿Por qué la Programación Orientada al Objeto?
-
- Hasta hace pocos años, se imponía un estilo de programación que ayudaba
- bastante a la redacción del código: la programación estructurada. En
- este estilo el diseño de un programa se centraba fundamentalmente en la
- estructuración del código que lo compone.
- Intentando hacer que este estilo se asemeje más a la percepción
- humana de los problemas, nace la OOP. El concepto fundamental es el de
- CLASE. Esta se define por un conjunto de características o datos y un
- conjunto de acciones que puede realizar. Cada ejemplo concreto de una
- clases sería un OBJETO.
-
- -pag. 4-
-
- Nos aclararemos mejor con un ejemplo: las funciones de tratamiento
- de ventanas. Con programación estructurada algunas funciones quedarían
- más o menos así:
-
- cFondo := AbreVent( nTop, nLeft, nBottom, nRight )
- .
- .
- .
- CierraVent( nTop, nLeft, nBottom, nRight, cFondo )
-
- Obviamente en este sistema tenemos que manejar una cantidad
- considerable de variables que en realidad se refieren a la misma
- entidad: la ventana. Un sistema algo más evolucionado y que tiene sus
- parecidos con la OOP es el manejo de Handles o arrays en el caso de
- Clipper:
-
- Handle := AbreVent( nTop, nLeft, nBottom, nRight )
- .
- .
- .
- CierraVent( Handle )
- Donde Handle contendría la toda la información que necesitamos para
- gestionar la ventana. ¿Qué ventajas añade la OOP a este sistema?
- -ENCAPSULACION: los datos referidos a un objeto son internos a éste y
- no existe posibilidad de confusión o repetición en su nombre, ya que
- siempre se especifica el objeto al que se refiere. Esto dota de una
- gran PORTABILIDAD intrasistemas a nuestro código. Este no debe ser
- modificado por instalarlo en una u otra aplicación. Lo mismo es
- aplicable a las funciones (métodos). p.e.:
- CLASE VENTANA
- VARIABLES nTop, nBottom, nLeft, nRight, lVisible, lMovible...
- MENSAJE Abrir METODO VNTAbrir
- MENSAGE Cerrar METODO VNTCerrar...
- FIN CLASE
-
- -HERENCIA: en el caso de que queramos un objeto que se comporte de
- distinta forma a la que ya teníamos programada, podemos "heredar" otra
- clase en la que sólo reescribiremos aquél comportamiento que varíe.
- Supongamos que las ventanas que vamos a utilizar ahora tienen "sombra",
- sólo reescribiríamos es anterior mensaje "Abrir" para que dibujase la
- sombra y después llamase al anterior método "Abrir".
-
- -POLIMORFISMO: es la capacidad para envíar el mismo mensaje a objetos
- de diferentes clases. Así, podemos enviar el mensaje "Pinta" o
- "ProcesaTecla" a un objeto menú, ventana, editor... No existe
- posibilidad de confundir el código asociado a cada uno.
-
- Resumiendo: para definir una clase primero necesitamos un nombre:
-
- CLASS VENTANA
-
- esto nos permitirá crear un objeto con la llamada obj := Ventana().
- Proseguimos definiendo sus variables:
-
- -pag. 5-
-
-
- VAR nTop, nLeft, nBottom, nRight, cFondo
-
- y las funciones (métodos) a ejecutar, con sus respectivos nombres
- (mensajes) con que serán reconocidas.
-
- CONSTRUCTOR New METHOD VNTNew( nTop, nLeft, nBottom, nRight )
- MESSAGE Cerrar METHOD VNTCerrar()
- MESSAGE Mover METHOD VNTMover( nTop, nLeft )
- END CLASS
-
- Ahora escribiremos el código asociado a cada método. Tendremos en
- cuenta que para referirnos a una variable del objeto que estamos
- procesando, la precederemos de Self: o su abreviatura ::
-
- METHOD VNTNew( nTop, nLeft, nBottom, nRight )
- ::cFondo := savescreen( nTop, nLeft, nBottom, nRight )
- @ nTop, nLeft CLEAR TO nBottom, nRIght
- ::nTop := nTop
- ::nLeft := nLeft
- ::nBottom:= nBottom
- ::nRight := nRight
- RETURN Self
-
- METHOD VNTCerrar()
- restscreen( ::nTop, ::nLeft, ::nBottom, ::nRight, ::cFondo )
-
- METHOD VNTMover( nTop, nLeft )
- LOCAL c
- c := savescreen( ::nTop, ::nLeft, ::nBottom, ::nRight )
- ::Cerrar()
- .
- .
- .
- ::nTop := nTop
- ::nLeft := nLeft
- restscreen( ::nTop, ::nLeft, ::nBottom, ::nRight, c )
- RETURN
-
- A la hora de utizar estas llamadas en nuestros programas:
-
- oVent := Ventana( 10, 4, 20, 60 ) //Crea el objeto ventana y lo
- . //almacena en oVent
- .
- .
- oVent:Mover( 11, 5 ) //Mensaje MOVER al objeto OVENT: ejecuta VNTMover
- .
- .
- oVent:Cerrar() //Mensaje CERRAR: restaura la pantalla
-
-
- GLOSARIO
- ========
- -CLASE: podríamos definirlo como un tipo de dato complejo que define
- varios datos y el código que actúa sobre ellos.
-
- -pag. 6-
-
-
- -CONSTRUCTOR: mensaje que es ejecutado automáticamente cada vez que se
- crea un objeto de la clase que se está definiendo.
- -HEREDAR o DERIVAR: proceso por el que comenzamos definiendo una clase
- con los métodos y datos que poseía otra.
- -HIJA o SUBCLASE: clase derivada o heredada de otra.
- -MENSAJE: nombre de la acción que ha de ejecutar el objeto.
- -METODO: nombre real de la función que se ejecutará cuando se presente
- el mensaje asociado a éste.
- -METODO VIRTUAL: es un caso especial que no realiza ninguna acción,
- pero está previsto que alguna(s) de las clases derivadas lo redefina
- con alguna acción en concreto.
- -RECEPTOR: objeto que recibe el mensaje. La sintaxis utilizada es:
- Objeto:Mensaje( [parámetros] )
- -OBJETO: es una variable (o instancia) que almacena lo que se ha
- definido en la CLASE, es decir, es un ejemplo concreto de una CLASE.
- -PADRE o SUPERCLASE:
- Clase de la que deriva o hereda otra. Cede sus variables y métodos a
- la clase Hija.
-
-
- SINTAXIS
- ========
- METASINTAXIS: lo que aparece encerrado entre corchetes [] es opcional.
- Donde aparece la barra vertical | hay que elegir una de las opciones
- que figuran a sus lados.
- Las palabras en Mayusculas son Palabras-Clave.
-
- 1-DEFINICION DE CLASES:
-
- #include "xclass.ch"
-
- CLASS NombreClase [ [Inherit] FROM ClasePadre [, ClasePadre2...] ]
-
- VAR|DATA NombreVar [, NombreVar2...]
- DELETE VAR NombreVar
- RENAME VAR NombreVar [ AS | TO | = ] NuevoNombre
-
- MESSAGE Mensaje[ ( [parms] ) ] METHOD Método[ ( [parámetros] ) ]
- MESSAGE Mensaje[ ( [parms] ) ] = Método[ ( [parámetros] ) ]
- MESSAGE Mensaje BLOCK CodeBLock
- MESSAGE Mensaje VIRTUAL
- MESSAGE Mensaje( [parámetros] )
- CONSTRUCTOR Mensaje METHOD Método( [parámetros] )
- CONSTRUCTOR Mensaje( [parámetros] )
- RENAME [MESSAGE | METHOD] Mensaje [ TO | AS | = ] NuevoMensaje
- DELETE MESSAGE | METHOD Mensaje
- END CLASS | ENDCLASS [NombreClase]
-
- 2-DEFINICION DE METODOS:
-
- METHOD [FUNCTION | PROCEDURE] Método( [parámetros] )
-
- ::Mensaje()[:Mensaje()...] | Self:Mensaje()[:Mensaje()..]
- obj:Mensaje()
-
- :super( [NombreClase] ):Mensaje( [parámetros] )
- :qsuper( [NombreClase,] VarStatic ):Mensaje( [parámetros] )
- ::parent:Mensaje( [parámetros] )
-
- -pag. 7-
-
- DESCRIPCION DE SENTENCIAS, EXPRESIONES Y FUNCIONES
- ==================================================
-
- CLASS
- =====
- Comienza la Definición de la Clase
-
- Syntaxis:
-
- CLASS NombreClase [ [Inherit] FROM ClasePadre [, ClasePadre2...] ]
-
- Devuelve (al utilizarla como llamada a función ):
-
- objeto perteneciente a esa clase.
-
- Argumentos
- NombreClase es el nombre dado a la clase. Se utilizará
- posteriormente como una función normal - NombreClase() -
- inicializando la clase si es la primera vez y retornando un objeto
- de ésta. Nótese que la primera vez que se llame a esta función la
- ejecución será más lenta que el resto, al igual que ocurre con las
- clases estándar en Clipper 5.0x.
-
- ClasePadre (opcional) es el nombre de una clase que, si se halla
- presente, proporcionará a esta toda su definición de variables,
- métodos y mensajes. En el caso de que se den varias Clases padre
- (herencia múltiple), la primera domina sobre las demás en caso de
- conflicto de nombres de variables o mensajes.
-
- Ejemplo
-
- CLASS PopMenu FROM Window, BaseMenu
-
-
- VAR o DATA
- ==========
- Define una variable de clase.
-
- Sintaxis
- VAR NombreVar [, NombreVar...]
-
- DATA funciona exactamente igual, se incluye por compatibilidad con
- OBJECTS.
-
- Ejemplo
- Var nContador, lEditable, aOpciones
-
-
- RENAME VAR
- ==========
- Cambia el nombre de una variable ya definida.
-
- Sintaxis
- RENAME VAR NombreVar [AS] [TO] [=] NuevoNombre
-
- Descripción
- Normalmente se utilizará RENAME VAR al heredar una clase en la que
- una variable de la clase padre interesa que sea renombrada por un
- presunto conflicto con una nueva variable del mismo nombre.
-
- -pag. 8-
-
-
- Este comando se incluye por compatibilidad con otros gestores de
- clase. El hecho de renombrar una variable, salvo raras excepciones,
- indica que metodológicamente no se está utilizando un buen diseño,
- aparte que podrá dar problemas al invocar a métodos-padre que
- trabajen con la variable renombrada.
-
- Ejemplo
- RENAME VAR nTop to nWTop
-
-
- DELETE VAR
- ==========
- Borra una definición de variable.
-
- Sintaxis
- DELETE VAR NombreVariable
-
- Descripción
- Este evita que la nueva clase posea una variable con ese nombre que,
- normalmente, existía en la clase padre. No se aconseja la
- utilización de estas técnicas salvo claros casos de escasez de
- memoria.
-
-
- MESSAGE
- =======
- Define un nuevo mensaje.
-
- Sintaxis
- MESSAGE NombreMensaje[ ( [parámetros] ) ]
-
- Descripción
- Equivale a:
- MESSAGE NombreMensaje METHOD NombreMensaje( parámetros )
-
- Ejemplos
- MESSAGE Borra, Comienza
- MESSAGE Acaba()
- MESSAGE Pinta( x, y )
-
-
- MESSAGE ... METHOD
- ==================
- Define un nuevo mensaje.
-
- Sintaxis
- MESSAGE NombreMensaje METHOD NombreMetodo( [parámetros] )
- MESSAGE NombreMensaje = NombreMetodo( [parámetros] )
- ( Ver Variantes )
-
- Descripción
- Con este comando definimos el mensaje NombreMensaje de la clase
- actual, indicando que ejecutará el método NombreMetodo, que necesita
- de [parámetros].
-
- -pag. 9-
-
-
- NombreMensaje y NombreMetodo deben cumplir las reglas de CLipper
- para denominación de funciones, especialmente señalar que sólo son
- significativos los 10 primeros caracteres.
-
- [parámetros] es la lista de parámetros que necesita el método para
- su ejecución. No es necesario que los nombres de éstos coincidan con
- los que se declaren en el método, pero sí es importante que
- coincidan en número.
-
- Con esto se logra que cuando se envíe NombreMensaje a un objeto de
- la clase que estamos definiendo, se ejecuta NombreMetodo. Ej:
- MESSAGE Mover METHOD WNDMover( nTop, nLeft )
- .
- .
- oWindow:Mover( 4, 6 ) //Ejecutará WNDMover( 4, 6 )
-
- La causa de tener nombres de métodos distintos a los de mensaje es
- poder utilizar las ventajas del polimorfismo: tener varios mensajes
- de distintas clases que se llamen igual. Se aconseja seguir siempre
- un método de asignación de nombres, que podría ser el hacer preceder
- al nombre del método de 3 caracteres que identifiquen la clase
- seguidos del nombre del mensaje.
-
- Ejemplos
- MESSAGE Pinta METHOD WNDPinta, Borra METHOD Borra()
- MESSAGE Muestra METHOD WNDPinta //2 mensajes al mismo Método
- MESSAGE ReSize METHOD WNDResize( nVer, nHor )
- MESSAGE Mover( nTop, nLeft ) = WNDMover
-
- Variantes
- Para mayor compatibilidad con otros sistemas de clases, se acepta
- una amplia variedad de formas en la definición de mensajes:
-
- MESSAGE Mess METHOD Meth
- MESSAGE Mess METHOD Meth()
- MESSAGE Mess METHOD Meth( a, b... )
- MESSAGE Mess() METHOD Meth
- MESSAGE Mess( a, b... ) METHOD Meth
- MESSAGE Mess( a, b... ) METHOD Meth()
- MESSAGE Mess( a, b... ) METHOD Meth( x, y, z )
-
-
- MESSAGE ... BLOCK
- =================
- Define un nuevo mensaje asociándolo a un CodeBlock
-
- Sintaxis
- MESSAGE NombreMensaje[(...)] BLOCK CodeBlock
-
- Descripción
- Al igual que MESSAGE...METHOD, este comando define un nuevo mensaje,
- pero asociándolo no con una función o método, sino directamente con
- un CodeBLock.
-
- -pag. 10-
-
-
- Se deben cumplir estas dos normas:
-
- 1- El primer parámetro que se declara en el CodeBlock debe ser Self.
- A continuación vendrá el resto de parámetros. No obstante, se
- utilizará posteriormente como un mensaje normal, como si no
- recibiese el parámetro Self. Ej:
-
- MESSAGE Baja BLOCK {| Self, nCuanto | ::nPos -= ::nCuanto }
-
- //Se llamará después: obj:Baja( 4 )
-
- 2 - El número máximo de parámetros que se le pueden pasar al
- CodeBlock, excluyendo a Self, es de 4 (5 contando el CB). Esto es
- así por razones de optimización de la velocidad.
-
- Ejemplo:
- MESSAGE Mover BLOCK {| Self, nT, nL | ::Cierra(), ::nTop := nT, ;
- ::nLeft := nL, ::Mostrar() }
-
-
- MESSAGE...VIRTUAL
- =================
- Define un mensaje virtual
-
- Sintaxis
- MESSAGE NombreMensaje VIRTUAL
-
- Propósito
- Hace que la clase reconozca a NombreMensaje pero sin que éste
- ejecute ningún código.
-
- Se utiliza en clases padres donde se prevee que sus derivadas sí
- tengan este mensaje. Así, cuando un método de la clase derivada
- llame a su método-padre y éste llame a NombreMensaje, realmente se
- ejecutará el Mensaje que fue redefinido en la clase hija.
-
- El hecho de incluirlo en la clase padre es por coherencia por otro
- método que llama a éste, en previsión de ser heredado.
-
- Ejemplo
- MESSAGE ProcesaTecla VIRTUAL
-
-
-
- CONSTRUCTOR ... METHOD
- ======================
- Define un nuevo mensaje de ejecución automática al crear un objeto.
-
- Sintaxis
- CONSTRUCTOR NombreMensaje [ METHOD NombreMetodo ]
-
- Descripción
- Funciona exactamente igual que MESSAGE...METHOD, salvo que con este
- comando se consigue que el método sea ejecutado cada vez que se crea
- un objeto. Los parámetros que recibe serán los mismos que se le
- pasó a la llamada de creación de la clase.
-
- Sólo puede haber un CONSTRUCTOR por clase.
-
- -pag. 11-
-
-
- Advertencia
- El mensaje NombreMensaje será heredado por todas las clases
- derivadas de ésta, pero no tendrá la consideración de CONSTRUCTOR
- para éstas.
-
- Ejemplo
- CONSTRUCTOR New METHOD WNDNew( nTop, nLeft, nBottom, nRight )
- //Dentro de la clase WINDOW
- //Será invocado con: Window( 3, 3, 16, 50 )
-
-
- RENAME MESSAGE
- ==============
- Cambia el nombre de un mensaje ya definido.
-
- Sintaxis:
- RENAME [MESSAGE | METHOD] NombreMensaje [TO] [AS] [=] NuevoNombre
-
- Propósito:
- Cambia el nombre de un mensaje por otro nuevo. Su utilidad es
- provocar unas llamadas a métodos padre más rápidas. Si tenemos un
- mensaje M1 que va a ser redefinido en la nueva clase, nos puede
- interesar redefinirlo, p.e. PM1, para que el nuevo método contenga
- en su código una llamada a PM1. Este método es más rápido que
- utilizar ::parent:M1() y algo más que :QSuper
-
- No obstante se debe sopesar este aumento en rendimiento con una
- pérdida en legibilidad.
-
- Ejemplo:
- RENAME MESSAGE Pinta TO SCPinta
- MESSAGE Pinta METHOD NuevoPinta()
-
-
- DELETE MESSAGE
- ==============
- Borra un mensaje ya definido.
-
- Sintaxis
- DELETE MESSAGE|METHOD NombreMensaje
-
- Propósito
- Elimina de la clase actúal NombreMensaje. Es utilizable en clases
- derivadas donde es seguro que no se utilizará, ni en ella ni en sus
- descendientes.
-
- Ejemplo
- DELETE MESSAGE Mover
-
-
- END CLASS
- =========
- Ver ENDCLASS
-
- -pag. 12-
-
-
- ENDCLASS
- =======
- Indica que ha finalizado la definición de la clase
-
- Sintaxis
- ENDCLASS [NombreClase]
-
- Ejemplo
- ENDCLASS Window
-
-
-
- METHOD
- ======
- Declara un método y sus parámetros
-
- Sintaxis
- METHOD [FUNCTION|PROCEDURE] idMétodo( [parámetros] )
-
- Propósito
- Al igual que FUNCTION declara una función, METHOD declara un método,
- que no es más que una función asociada a un mensaje.
-
- Las palabras clave FUNCTION o PROCEDURE son opcionales y se incluyen
- por compatibilidad con oClip y otras.
-
- El código del método dispondrá, aparte de las declaradas ya, una
- variable local más: el objeto Self: (abrebiado ::). Este objeto
- representa el actual sobre el que se está ejecutando el método.
-
- Ejemplo
- METHOD Mover( nTop, nLeft )
- ::Restaurar()
- ::nBottom += nTop - ::nTop
- ::nRight += nLeft - ::nLeft
- ::nTop := nTop
- ::nLeft := nLeft
- RETURN ::Abrir()
-
-
- PARENT
- ======
- Ejecuta un método asociado con un mensaje de la clase padre.
-
- Sintaxis
- ::parent:Mensaje( [parámetros] )
-
- Descricpión
- ::parent envía Mensaje al objecto actual pero haciendo que se
- ejecute el método que estaba asociado con Mensaje en la clase padre,
- no en la actual.
-
- Esto, obviamente, sólo es necesario cuando en la clase Hijo se ha
- redefinido un mensaje.
-
- -pag. 13-
-
-
- Ejemplo:
- CLASS VentanaSombra FROM Ventana
- .
- .
- MESSAGE Pinta METHOD VNSPinta( aEsquinas )
- END CLASS
-
- METHOD VNSPinta( aEsquinas )
- Sombra( aEsquinas ) //DIbuja una sombra
- ::parent:Pinta( aEsquinas ) //El método padre hace el resto
-
-
- SUPER
- =====
- Ejecuta un método asociado con un mensaje de la clase padre.
-
- Sintaxis
- :Super( [NombreClase] ):Mensaje( [parámetros] )
-
- Descripción
- Su función es la misma que la de ::PARENT. Esta forma es por
- compatibilidad con SuperClass. Obsérvese que mientras PARENT se
- antecede de doble dos puntos, Super sólo lo hace con uno.
-
- :Super tiene la ventaja sobre ::parent de que es posible especificar
- de qué clase se obtiene el método de mensaje. Si [NombreClase] es
- nulo, buscará el mensaje en la clase padre. Si [NombreClase] existe,
- lo buscará en ella. Es necesario si invocamos a un método de una
- clase que no es la primera-padre, es decir, en casos de herencia
- múltiple donde queremos especificar a qué clase padre nos referimos.
-
- Ejemplo
- METHOD VNSPinta( aEsquinas )
- Sombra( aEsquinas ) //DIbuja una sombra
- :super():Pinta( aEsquinas ) //El método padre hace el resto
-
-
- QSUPER
- ======
- Ejecuta un método asociado con un mensaje de la clase padre.
-
- Sintaxis
- :Qsuper( [NombreClase,] VarStatic ):Mensaje( [parámetros] )
-
- Descripción
- Su función es exactamente la misma que :Super().
-
- La ventaja es éste método es que ofrece una forma mucho más rápida
- de ejecutar las llamadas al método. Esto se logra con el uso de una
- variable estática (VarStatic). La primera vez que es ejecutada,
- funciona igual que :Super(), pero el resultado de la búsqueda del
- método, que es lo que más tiempo lleva, se queda almacenado en
- VarStatic, de forma que en sucesivas llamadas irá mucho más rápido.
-
- Ejemplo
- METHOD VNSPinta( aEsquinas )
- STATIC b
- Sombra( aEsquinas ) //Dibuja una sombra
- :Qsuper( b ):Pinta( aEsquinas ) //El método padre hace el resto
-
- -pag. 14-
-
-
- CLASSH
- ======
- Mensaje que devuelve el identificador (handle) de la clase
-
- Sintaxis
- obj:ClassH ---> nHandle
-
- Descripción
- ClassH es un mensaje estándar para todas las clases. Retorna el
- manejador numérico que utiliza Clipper para identificar la clase.
-
- Ejemplo
- if obj1:ClassH == obj2:ClassH
- ? "Obj1 y Obj2 son de la misma clase"
- else
- ? "Obj1 y Obj2 son de distintas clases"
- endif
-
-
- CLASSNAME
- =========
- Mensaje que devuelve el nombre de la clase.
-
- Sintaxis
- obj:ClassName() --->cNombreClase
-
- Descripción
- ClassName es un mensaje estándar para todas las clases. Retorna una
- cadena de caracteres con el nombre de la clase de "obj".
-
- Ejemplo
- Function MiraVentana( oVentana )
- if oVentana:ClassName() == "GET"
- ? "¿Qué hace un objeto Get aquí?"
- RETURN
- endif
-
-
-
-
- FUNCIONES.=
- ===========
-
- OCLONE
- ======
- Devuelve un duplicado de un objeto.
-
- Sintaxis
- oClone( objeto ) --> oNew
-
- Descripción.
- Al igual que aclone() con los arrays, oclone() devuelve un duplicado
- del objeto. La asignación normal ( oNew := objeto ) hace que oNew
- sea un "puntero" a "objeto", de forma que si modificamos uno el
- cambio afecta a ambos. oClone() efectúa un duplicado real.
-
- -pag. 15-
-
-
- Al igual que aclone() esta copia no es recursiva. Esto quiere decir
- que si uno de los elementos que contiene el objeto es un array u
- otro objeto, el nuevo objeto contendrá nuevos punteros al array u
- objeto, pero éstos siguen siendo el mismo, no se duplican.
-
- Ejemplo
- oVentana := Window():New( 2, 2, 10, 40 )
- oVentana2 := oClone( oVentana )
-
-
- NEWOBJECT()
- ===========
- Devuelve un objeto nuevo sin inicializar.
-
- Sintaxis
- NewObject( nHandleClase ) --->oNew
-
- Descripción
- NewObject(), que se incluye por compatibilidad con SuperClass,
- devuelve un objeto no inicializado de la clase que tiene a
- nHandleClase por identificador.
-
- Ejemplo
- FUNCTION DameObjetoVacio( obj )
- RETURN NewObject( obj:ClassH )
-
-
- oSAVE
- =====
- Graba un objeto en disco.
-
- Sintaxis
- oSave( objeto, cNombreFichero )
-
- Descripción
- oSave graba un objeto (o cualquier tipo de variable) en disco con el
- nombre "cNombreFichero", pudiendo después ser recuperado con
- oLoad().
-
- Las lógicas exepciones a ésto son:
- -Los elementos de tipo CodeBlock
- -Los arrays u objetos doblemente recursivos, p.e.:
- a := { NIL }
- a[ 1 ] := a
- -Las clases estándar de Clipper. En realidad sí pueden ser grabadas,
- pero no leídas :-). Lo siento.
-
- Ejemplo
- oSave( oArbol1, "001.ARB" )
- oSave( "Cadena de caracteres", "PRUEBA.CHR" )
-
-
- -pag. 16-
-
-
- oLOAD
- =====
- Lee un objeto del disco
-
- Sintaxis
- oLoad( cNombreFichero ) --->objeto
-
- Descripción
- oLoad() lee un objeto (o cualquier tipo de variable) desde un
- fichero en disco con el nombre "cNombreFichero" y lo devuelve como
- resultado.
-
- Aspectos a tener en cuenta:
- -Lógicamente no se pueden leer elementos del tipo CodeBlock. Si hay
- grabado alguno, se retorna como un NIL.
- -Para leer un objeto es necesario que antes hayamos tenido en
- memoria un objeto de la misma clase o alguna de las derivadas. Así
- que esto no es solución para tener varios objetos grabados en disco
- e intentar leerlos en un programa que no contiene las definiciones
- de las clases.
-
- Ejemplo
-
- oArb1 := Arbol() //Arbol es una clase
- oArb1 := oLoad( "001.ARB" )
-
- qout( oLoad( "PRUEBA.CHR" ) )
-
-
-
- PSEUDO-COMANDOS
- ===============
- Estos son algunos aspectos sintácticos de XClass que, aunque no
- hacen nada, se incluyen por razones de compatibilidad con otros
- gestores de clases. Estos son:
-
- en la definición de clases:
- PROTECTED
- EXPORTED
- READ ONLY
-
- PROTECTED METHODS
- PUBLIC METHODS
- PRIVATE METHODS
- Todos ellos se admiten por compatibilidad con SuperClass aunque en
- XClass 2.0 todos sean variables y métodos públicos. Lo mismo sucede
- con VAR...READONLY o VAR...HIDDEN
-
-
-
- DEBUGGER
- ========
- XClass ofrece total compatibilidad con el Debugger de Clipper 5.01.
- No obstante a veces aparece información extraña sobre variables
- locales cuando se ejecutan ciertos métodos. Si apareciese este
- efecto, basta incluir la directiva
-
- -pag. 17-
-
-
- #define DEBUG
-
- o bien compilar con
-
- CLIPPER fichero.prg /DDEBUG
-
-
-
- METODOS-PADRE
- =============
- Varias veces se ha hecho referencia en este manual a la problemática
- de los métodos-padre. Llamamos así a los métodos de una clase padre
- que han sido redefinidos por otros en la clase hijo pero que, no
- obstante, a veces necesitan ser llamados.
-
- El ejemplo típico es el de una subclase VENTANA_CON_SOMBRA, que
- redefine el método PINTA para dibujar primero la sombra, pero
- después lo más cómodo sería ejecutar el método PINTA de la clase
- padre, que ejecutaría el resto de la tarea.
-
- El primer problema es la velocidad. Ya que Clipper 5.01 no
- implementa de forma directa la herencia, es necesario utilizar unos
- sistemas de localización del método padre. Así, en un método donde
- se necesite una alta velocidad y se ejecute repetidas veces,
- podremos recurrir a :Qsuper()
-
- El segundo problema es el conflicto de nombres. Si derivamos la
- clase POPMENU de las clases MENU y VENTANA, puede haber mensajes
- idénticos en ambas clases padre. Siempre tendrá prioridad aquellos
- que hallan sido definidos en la primera clase que aparece como
- heredada, en el siguiente ejemplo sería MENU:
-
- CLASS POPMENU FROM MENU, VENTANA
-
- Si queremos llamar al mensaje PINTA, que existe en MENU y VENTANA,
- la llamada
- :Super():Pinta()
- ejecutará el PINTA() de la clase MENU, mientras que
- :Super( VENTANA ):Pinta()
- ejecutará el PINTA() de la clase VENTANA.
-