home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / CLIPPER / DATABASE / XCLAS20P.ZIP / XCLASS.DOC < prev    next >
Encoding:
Text File  |  1993-03-25  |  28.0 KB  |  946 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12. ╔═════════════════════════════════════════════════════════════════════╗
  13. ║                                                                     ║
  14. ║                              XCLASS 2.00                            ║
  15. ║                                                                     ║
  16. ║   Extensión a Clipper 5.01 para Programación Orientada al Objeto    ║
  17. ║                                                                     ║
  18. ║                     (c) 1993 Carlos Ruiz Ruiz                       ║
  19. ║                                                                     ║
  20. ╚═════════════════════════════════════════════════════════════════════╝
  21.  
  22.  
  23.                  Versión de Dominio Público
  24.  
  25.                         Prohibida su Venta
  26.  
  27.  
  28.  
  29.                          -pag. 2-
  30.  
  31.  
  32.  
  33.  
  34.  
  35.                 INDICE
  36.                 ======
  37.  
  38.       CARACTERISTICAS...................................3
  39.  
  40.       AGRADECIMIENTOS...................................3
  41.  
  42.       INTRODUCCION A LA OOP.............................3
  43.  
  44.       GLOSARIO..........................................5
  45.  
  46.       SINTAXIS..........................................6
  47.  
  48.       SENTENCIAS, EXPRESIONES Y FUNCIONES...............7
  49.      -CLASS.........................................7
  50.      -VAR / DATA....................................7
  51.      -RENAME VAR....................................7
  52.      -DELETE VAR....................................8
  53.      -MESSAGE.......................................8
  54.      -MESSAGE METHOD................................8
  55.      -MESSAGE BLOCK.................................9
  56.      -MESSAGE VIRTUAL..............................10
  57.      -CONSTRUCTOR METHOD...........................10
  58.      -RENAME MESSAGE...............................11
  59.      -DELETE MESSAGE...............................11
  60.      -ENDCLASS.....................................12
  61.      -METHOD.......................................12
  62.      -PARENT.......................................12
  63.      -SUPER........................................13
  64.      -QSUPER.......................................13
  65.      -CLASSH.......................................14
  66.      -CLASSNAME....................................14
  67.      FUNCIONES:
  68.      -OCLONE.......................................14
  69.      -NEWOBJECT....................................15
  70.      -OSAVE........................................15
  71.      -OLOAD........................................16
  72.  
  73.       PSEUDO-COMANDOS..................................16
  74.  
  75.       DEBUGGER.........................................16
  76.  
  77.       METODOS-PADRE....................................17
  78.  
  79.  
  80.  
  81.                          -pag. 3-
  82.  
  83.  
  84.    XClass es una extensión del compilador Clipper para Programación
  85. Orientada al Objeto. Está basado en las funciones internas no
  86. documentadas de la librería Clipper y sólo donde estas no llegan se ha
  87. hecho necesaria la programación adicional.
  88.  
  89.  
  90. CARACTERISTICAS
  91. ===============
  92. -Soporte de herencia múltiple y simple.
  93. -Soporte de métodos constructores.
  94. -Creación de clases en tiempo de ejecución.
  95. -Asociación de mensajes con métodos (funciones) o Code Blocks.
  96. -Mensajes virtuales.
  97. -Compatibilidad con el Debugger
  98. -Código eficiente y compacto.
  99. -Posibilidad de redefinición y borrado de mensajes y variables en
  100. clases derivadas.
  101. -Método rápido de acceso a los mensajes-padre.
  102. -Compatibilidad con una amplia variedad de sintaxis, especialmente con
  103. SuperClass 1.2
  104. -GRABACION y LECTURA en DISCO de cualquier OBJETO
  105. -Modularidad en el diseñó. Sólo se linkan aquellos módulos que son 
  106. realmente utilizados.
  107.  
  108.  
  109. AGRADECIMIENTOS
  110. ===============
  111.    XClass es el producto de un pequeño aporte del autor a otras grandes
  112. ideas que han servido de base, especialmente de:
  113. -Peter M. Freese, autor de oClip, primera librería de dominio público.
  114. -Chris Sennit, autor de SuperClass.
  115. -Antonio Linares, autor de ClassMaker, Dialog, Object... y esperemos
  116. que mucho más.
  117. -Francisco Pulpón, que aportó ideas muy buenas para mejorar las
  118. anteriores.
  119. -Antonio Rojo, autor de OopClip.
  120.  
  121.  
  122. INTRODUCCION
  123. ============
  124. ¿Por qué la Programación Orientada al Objeto?
  125.  
  126. Hasta hace pocos años, se imponía un estilo de programación que ayudaba
  127. bastante a la redacción del código: la programación estructurada. En
  128. este estilo el diseño de un programa se centraba fundamentalmente en la
  129. estructuración del código que lo compone.
  130.    Intentando hacer que este estilo se asemeje más a la percepción
  131. humana de los problemas, nace la OOP. El concepto fundamental es el de
  132. CLASE. Esta se define por un conjunto de características o datos y un
  133. conjunto de acciones que puede realizar. Cada ejemplo concreto de una
  134. clases sería un OBJETO.
  135.  
  136.                          -pag. 4-
  137.  
  138.    Nos aclararemos mejor con un ejemplo: las funciones de tratamiento
  139. de ventanas. Con programación estructurada algunas funciones quedarían
  140. más o menos así:
  141.  
  142. cFondo := AbreVent( nTop, nLeft, nBottom, nRight )
  143. .
  144. .
  145. .
  146. CierraVent( nTop, nLeft, nBottom, nRight, cFondo )
  147.  
  148.    Obviamente en este sistema tenemos que manejar una cantidad
  149. considerable de variables que en realidad se refieren a la misma
  150. entidad: la ventana. Un sistema algo más evolucionado y que tiene sus
  151. parecidos con la OOP es el manejo de Handles o arrays en el caso de
  152. Clipper:
  153.  
  154. Handle := AbreVent( nTop, nLeft, nBottom, nRight )
  155. .
  156. .
  157. .
  158. CierraVent( Handle )
  159.    Donde Handle contendría la toda la información que necesitamos para
  160. gestionar la ventana. ¿Qué ventajas añade la OOP a este sistema?
  161. -ENCAPSULACION: los datos referidos a un objeto son internos a éste y
  162. no existe posibilidad de confusión o repetición en su nombre, ya que
  163. siempre se especifica el objeto al que se refiere. Esto dota de una
  164. gran PORTABILIDAD intrasistemas a nuestro código. Este no debe ser
  165. modificado por instalarlo en una u otra aplicación. Lo mismo es
  166. aplicable a las funciones (métodos). p.e.:
  167. CLASE VENTANA
  168. VARIABLES nTop, nBottom, nLeft, nRight, lVisible, lMovible...
  169. MENSAJE Abrir METODO VNTAbrir
  170. MENSAGE Cerrar METODO VNTCerrar...
  171. FIN CLASE
  172.  
  173. -HERENCIA: en el caso de que queramos un objeto que se comporte de
  174. distinta forma a la que ya teníamos programada, podemos "heredar" otra
  175. clase en la que sólo reescribiremos aquél comportamiento que varíe.
  176. Supongamos que las ventanas que vamos a utilizar ahora tienen "sombra",
  177. sólo reescribiríamos es anterior mensaje "Abrir" para que dibujase la
  178. sombra y después llamase al anterior método "Abrir".
  179.  
  180. -POLIMORFISMO: es la capacidad para envíar el mismo mensaje a objetos
  181. de diferentes clases. Así, podemos enviar el mensaje "Pinta" o
  182. "ProcesaTecla" a un objeto menú, ventana, editor... No existe
  183. posibilidad de confundir el código asociado a cada uno.
  184.  
  185. Resumiendo: para definir una clase primero necesitamos un nombre:
  186.  
  187. CLASS VENTANA
  188.  
  189. esto nos permitirá crear un objeto con la llamada obj := Ventana().
  190. Proseguimos definiendo sus variables:
  191.  
  192.                          -pag. 5-
  193.  
  194.  
  195. VAR nTop, nLeft, nBottom, nRight, cFondo
  196.  
  197. y las funciones (métodos) a ejecutar, con sus respectivos nombres
  198. (mensajes) con que serán reconocidas.
  199.  
  200. CONSTRUCTOR New METHOD VNTNew( nTop, nLeft, nBottom, nRight )
  201. MESSAGE Cerrar  METHOD VNTCerrar()
  202. MESSAGE Mover   METHOD VNTMover( nTop, nLeft )
  203. END CLASS
  204.  
  205. Ahora escribiremos el código asociado a cada método. Tendremos en
  206. cuenta que para referirnos a una variable del objeto que estamos
  207. procesando, la precederemos de Self: o su abreviatura ::
  208.  
  209. METHOD VNTNew( nTop, nLeft, nBottom, nRight )
  210.   ::cFondo := savescreen( nTop, nLeft, nBottom, nRight )
  211.   @ nTop, nLeft CLEAR TO nBottom, nRIght
  212.   ::nTop   := nTop
  213.   ::nLeft  := nLeft
  214.   ::nBottom:= nBottom
  215.   ::nRight := nRight
  216. RETURN Self
  217.  
  218. METHOD VNTCerrar()
  219.   restscreen( ::nTop, ::nLeft, ::nBottom, ::nRight, ::cFondo )
  220.  
  221. METHOD VNTMover( nTop, nLeft )
  222.   LOCAL c
  223.   c := savescreen( ::nTop, ::nLeft, ::nBottom, ::nRight )
  224.   ::Cerrar()
  225.   .
  226.   .
  227.   .
  228.   ::nTop  := nTop
  229.   ::nLeft := nLeft
  230.   restscreen( ::nTop, ::nLeft, ::nBottom, ::nRight, c )
  231. RETURN
  232.  
  233. A la hora de utizar estas llamadas en nuestros programas:
  234.  
  235. oVent := Ventana( 10, 4, 20, 60 )    //Crea el objeto ventana y lo
  236. .                                    //almacena en oVent
  237. .
  238. .
  239. oVent:Mover( 11, 5 )  //Mensaje MOVER al objeto OVENT: ejecuta VNTMover
  240. .
  241. .
  242. oVent:Cerrar()   //Mensaje CERRAR: restaura la pantalla
  243.  
  244.  
  245. GLOSARIO
  246. ========
  247. -CLASE: podríamos definirlo como un tipo de dato complejo que define
  248. varios datos y el código que actúa sobre ellos.
  249.  
  250.                          -pag. 6-
  251.  
  252.  
  253. -CONSTRUCTOR: mensaje que es ejecutado automáticamente cada vez que se
  254. crea un objeto de la clase que se está definiendo.
  255. -HEREDAR o DERIVAR: proceso por el que comenzamos definiendo una clase
  256. con los métodos y datos que poseía otra.
  257. -HIJA o SUBCLASE: clase derivada o heredada de otra.
  258. -MENSAJE: nombre de la acción que ha de ejecutar el objeto.
  259. -METODO:  nombre real de la función que se ejecutará cuando se presente
  260. el mensaje asociado a éste.
  261. -METODO VIRTUAL: es un caso especial que no realiza ninguna acción,
  262. pero está previsto que alguna(s) de las clases derivadas lo redefina
  263. con alguna acción en concreto.
  264. -RECEPTOR: objeto que recibe el mensaje. La sintaxis utilizada es:
  265. Objeto:Mensaje( [parámetros] )
  266. -OBJETO:  es una variable (o instancia) que almacena lo que se ha
  267. definido en la CLASE, es decir, es un ejemplo concreto de una CLASE.
  268. -PADRE o SUPERCLASE:
  269. Clase de la que deriva o hereda otra.  Cede sus variables y métodos a
  270. la clase Hija.
  271.  
  272.  
  273. SINTAXIS
  274. ========
  275. METASINTAXIS: lo que aparece encerrado entre corchetes [] es opcional.
  276. Donde aparece la barra vertical | hay que elegir una de las opciones
  277. que figuran a sus lados.
  278. Las palabras en Mayusculas son  Palabras-Clave.
  279.  
  280. 1-DEFINICION DE CLASES:
  281.  
  282. #include "xclass.ch"
  283.  
  284. CLASS NombreClase [ [Inherit] FROM ClasePadre [, ClasePadre2...] ]
  285.  
  286. VAR|DATA NombreVar [, NombreVar2...]
  287. DELETE VAR NombreVar
  288. RENAME VAR NombreVar [ AS | TO | = ] NuevoNombre
  289.  
  290. MESSAGE Mensaje[ ( [parms] ) ] METHOD Método[ ( [parámetros] ) ]
  291. MESSAGE Mensaje[ ( [parms] ) ] = Método[ ( [parámetros] ) ]
  292. MESSAGE Mensaje  BLOCK CodeBLock
  293. MESSAGE Mensaje  VIRTUAL
  294. MESSAGE Mensaje( [parámetros] )
  295. CONSTRUCTOR Mensaje METHOD Método( [parámetros] )
  296. CONSTRUCTOR Mensaje( [parámetros] )
  297. RENAME [MESSAGE | METHOD] Mensaje [ TO | AS | = ] NuevoMensaje
  298. DELETE MESSAGE | METHOD Mensaje
  299. END CLASS | ENDCLASS [NombreClase]
  300.  
  301. 2-DEFINICION DE METODOS:
  302.  
  303. METHOD [FUNCTION | PROCEDURE] Método( [parámetros] )
  304.  
  305. ::Mensaje()[:Mensaje()...] | Self:Mensaje()[:Mensaje()..]
  306. obj:Mensaje()
  307.  
  308. :super( [NombreClase] ):Mensaje( [parámetros] )
  309. :qsuper( [NombreClase,] VarStatic ):Mensaje( [parámetros] )
  310. ::parent:Mensaje( [parámetros] )
  311.  
  312.                          -pag. 7-
  313.  
  314. DESCRIPCION DE SENTENCIAS, EXPRESIONES Y FUNCIONES
  315. ==================================================
  316.  
  317. CLASS
  318. =====
  319.   Comienza la Definición de la Clase
  320.  
  321. Syntaxis:
  322.  
  323.   CLASS NombreClase [ [Inherit] FROM ClasePadre [, ClasePadre2...] ]
  324.  
  325. Devuelve (al utilizarla como llamada a función ):
  326.  
  327.    objeto perteneciente a esa clase.
  328.  
  329. Argumentos
  330.    NombreClase es el nombre dado a la clase. Se utilizará
  331.    posteriormente como una función normal - NombreClase() -
  332.    inicializando la clase si es la primera vez y retornando un objeto
  333.    de ésta. Nótese que la primera vez que se llame a esta función la
  334.    ejecución será más lenta que el resto, al igual que ocurre con las
  335.    clases estándar en Clipper 5.0x.
  336.  
  337.    ClasePadre (opcional) es el nombre de una clase que, si se halla
  338.    presente, proporcionará a esta toda su definición de variables,
  339.    métodos y mensajes. En el caso de que se den varias Clases padre
  340.    (herencia múltiple), la primera domina sobre las demás en caso de
  341.    conflicto de nombres de variables o mensajes.
  342.  
  343. Ejemplo
  344.  
  345.    CLASS PopMenu FROM Window, BaseMenu
  346.  
  347.  
  348. VAR o DATA
  349. ==========
  350.    Define una variable de clase.
  351.  
  352. Sintaxis
  353.    VAR NombreVar [, NombreVar...]
  354.  
  355.    DATA funciona exactamente igual, se incluye por compatibilidad con
  356.    OBJECTS.
  357.  
  358. Ejemplo
  359.    Var nContador, lEditable, aOpciones
  360.  
  361.  
  362. RENAME VAR
  363. ==========
  364.    Cambia el nombre de una variable ya definida.
  365.  
  366. Sintaxis
  367.    RENAME VAR NombreVar [AS] [TO] [=] NuevoNombre
  368.  
  369. Descripción
  370.    Normalmente se utilizará RENAME VAR al heredar una clase en la que
  371.    una variable de la clase padre interesa que sea renombrada por un
  372.    presunto conflicto con una nueva variable del mismo nombre.
  373.  
  374.                          -pag. 8-
  375.  
  376.  
  377.    Este comando se incluye por compatibilidad con otros gestores de
  378.    clase. El hecho de renombrar una variable, salvo raras excepciones,
  379.    indica que metodológicamente no se está utilizando un buen diseño,
  380.    aparte que podrá dar problemas al invocar a métodos-padre que
  381.    trabajen con la variable renombrada.
  382.  
  383. Ejemplo
  384.    RENAME VAR nTop to nWTop
  385.  
  386.  
  387. DELETE VAR
  388. ==========
  389.    Borra una definición de variable.
  390.  
  391. Sintaxis
  392.    DELETE VAR NombreVariable
  393.  
  394. Descripción
  395.    Este evita que la nueva clase posea una variable con ese nombre que,
  396.    normalmente, existía en la clase padre. No se aconseja la
  397.    utilización de estas técnicas salvo claros casos de escasez de
  398.    memoria.
  399.  
  400.  
  401. MESSAGE
  402. =======
  403.    Define un nuevo mensaje.
  404.  
  405. Sintaxis
  406.    MESSAGE NombreMensaje[ ( [parámetros] ) ]
  407.  
  408. Descripción
  409.    Equivale a:
  410.    MESSAGE NombreMensaje METHOD NombreMensaje( parámetros )
  411.  
  412. Ejemplos
  413.    MESSAGE Borra, Comienza
  414.    MESSAGE Acaba()
  415.    MESSAGE Pinta( x, y )
  416.  
  417.  
  418. MESSAGE ... METHOD
  419. ==================
  420.    Define un nuevo mensaje.
  421.  
  422. Sintaxis
  423.    MESSAGE NombreMensaje METHOD  NombreMetodo( [parámetros] )
  424.    MESSAGE NombreMensaje   =     NombreMetodo( [parámetros] )
  425.    ( Ver Variantes )
  426.  
  427. Descripción
  428.    Con este comando definimos el mensaje NombreMensaje de la clase
  429.    actual, indicando que ejecutará el método NombreMetodo, que necesita
  430.    de [parámetros].
  431.  
  432.                          -pag. 9-
  433.  
  434.  
  435.    NombreMensaje y NombreMetodo deben cumplir las reglas de CLipper
  436.    para denominación de funciones, especialmente señalar que sólo son
  437.    significativos los 10 primeros caracteres.
  438.  
  439.    [parámetros] es la lista de parámetros que necesita el método para
  440.    su ejecución. No es necesario que los nombres de éstos coincidan con
  441.    los que se declaren en el método, pero sí es importante que
  442.    coincidan en número.
  443.  
  444.    Con esto se logra que cuando se envíe NombreMensaje a un objeto de
  445.    la clase que estamos definiendo, se ejecuta NombreMetodo. Ej:
  446.    MESSAGE Mover  METHOD WNDMover( nTop, nLeft )
  447.    .
  448.    .
  449.    oWindow:Mover( 4, 6 )   //Ejecutará WNDMover( 4, 6 )
  450.  
  451.    La causa de tener nombres de métodos distintos a los de mensaje es
  452.    poder utilizar las ventajas del polimorfismo: tener varios mensajes
  453.    de distintas clases que se llamen igual. Se aconseja seguir siempre
  454.    un método de asignación de nombres, que podría ser el hacer preceder
  455.    al nombre del método de 3 caracteres que identifiquen la clase
  456.    seguidos del nombre del mensaje.
  457.  
  458. Ejemplos
  459.    MESSAGE Pinta   METHOD WNDPinta, Borra METHOD Borra()
  460.    MESSAGE Muestra METHOD WNDPinta    //2 mensajes al mismo Método
  461.    MESSAGE ReSize  METHOD WNDResize( nVer, nHor )
  462.    MESSAGE Mover( nTop, nLeft ) = WNDMover
  463.  
  464. Variantes
  465.    Para mayor compatibilidad con otros sistemas de clases, se acepta
  466.    una amplia variedad de formas en la definición de mensajes:
  467.  
  468.    MESSAGE Mess    METHOD Meth
  469.    MESSAGE Mess    METHOD Meth()
  470.    MESSAGE Mess    METHOD Meth( a, b... )
  471.    MESSAGE Mess()  METHOD Meth
  472.    MESSAGE Mess( a, b... ) METHOD Meth
  473.    MESSAGE Mess( a, b... ) METHOD Meth()
  474.    MESSAGE Mess( a, b... ) METHOD Meth( x, y, z )
  475.  
  476.  
  477. MESSAGE ... BLOCK
  478. =================
  479.    Define un nuevo mensaje asociándolo a un CodeBlock
  480.  
  481. Sintaxis
  482.    MESSAGE NombreMensaje[(...)] BLOCK CodeBlock
  483.  
  484. Descripción
  485.    Al igual que MESSAGE...METHOD, este comando define un nuevo mensaje,
  486.    pero asociándolo no con una función o método, sino directamente con
  487.    un CodeBLock.
  488.  
  489.                          -pag. 10-
  490.  
  491.  
  492.    Se deben cumplir estas dos normas:
  493.  
  494.    1- El primer parámetro que se declara en el CodeBlock debe ser Self.
  495.    A continuación vendrá el resto de parámetros. No obstante, se
  496.    utilizará posteriormente como un mensaje normal, como si no
  497.    recibiese el parámetro Self. Ej:
  498.  
  499.       MESSAGE Baja BLOCK {| Self, nCuanto | ::nPos -= ::nCuanto }
  500.  
  501.       //Se llamará después: obj:Baja( 4 )
  502.  
  503.    2 - El número máximo de parámetros que se le pueden pasar al
  504.    CodeBlock, excluyendo a Self, es de 4 (5 contando el CB). Esto es
  505.    así por razones de optimización de la velocidad.
  506.  
  507. Ejemplo:
  508.    MESSAGE Mover BLOCK {| Self, nT, nL | ::Cierra(), ::nTop := nT, ;
  509.              ::nLeft := nL,  ::Mostrar() }
  510.  
  511.  
  512. MESSAGE...VIRTUAL
  513. =================
  514.    Define un mensaje virtual
  515.  
  516. Sintaxis
  517.    MESSAGE NombreMensaje VIRTUAL
  518.  
  519. Propósito
  520.    Hace que la clase reconozca a NombreMensaje pero sin que éste
  521.    ejecute ningún código.
  522.  
  523.    Se utiliza en clases padres donde se prevee que sus derivadas sí
  524.    tengan este mensaje. Así, cuando un método de la clase derivada
  525.    llame a su método-padre y éste llame a NombreMensaje, realmente se
  526.    ejecutará el Mensaje que fue redefinido en la clase hija.
  527.  
  528.    El hecho de incluirlo en la clase padre es por coherencia por otro
  529.    método que llama a éste, en previsión de ser heredado.
  530.  
  531. Ejemplo
  532.    MESSAGE ProcesaTecla VIRTUAL
  533.  
  534.  
  535.  
  536. CONSTRUCTOR ... METHOD
  537. ======================
  538.    Define un nuevo mensaje de ejecución automática al crear un objeto.
  539.  
  540. Sintaxis
  541.    CONSTRUCTOR NombreMensaje [ METHOD NombreMetodo ]
  542.  
  543. Descripción
  544.    Funciona exactamente igual que MESSAGE...METHOD, salvo que con este
  545.    comando se consigue que el método sea ejecutado cada vez que se crea
  546.    un objeto. Los parámetros que recibe serán los mismos que se le
  547.    pasó a la llamada de creación de la clase.
  548.  
  549.    Sólo puede haber un CONSTRUCTOR por clase.
  550.  
  551.                          -pag. 11-
  552.  
  553.  
  554. Advertencia
  555.    El mensaje NombreMensaje será heredado por todas las clases
  556.    derivadas de ésta, pero no tendrá la consideración de CONSTRUCTOR
  557.    para éstas.
  558.  
  559. Ejemplo
  560.    CONSTRUCTOR New METHOD WNDNew( nTop, nLeft, nBottom, nRight )
  561.    //Dentro de la clase WINDOW
  562.    //Será invocado con:  Window( 3, 3, 16, 50 )
  563.  
  564.  
  565. RENAME MESSAGE
  566. ==============
  567.    Cambia el nombre de un mensaje ya definido.
  568.  
  569. Sintaxis:
  570.    RENAME [MESSAGE | METHOD] NombreMensaje [TO] [AS] [=] NuevoNombre
  571.  
  572. Propósito:
  573.    Cambia el nombre de un mensaje por otro nuevo. Su utilidad es
  574.    provocar unas llamadas a métodos padre más rápidas. Si tenemos un
  575.    mensaje M1 que va a ser redefinido en la nueva clase, nos puede
  576.    interesar redefinirlo, p.e.  PM1, para que el nuevo método contenga
  577.    en su código una llamada a PM1. Este método es más rápido que
  578.    utilizar ::parent:M1() y algo más que :QSuper
  579.  
  580.    No obstante se debe sopesar este aumento en rendimiento con una
  581.    pérdida en legibilidad.
  582.  
  583. Ejemplo:
  584.    RENAME MESSAGE Pinta TO SCPinta
  585.    MESSAGE Pinta METHOD NuevoPinta()
  586.  
  587.  
  588. DELETE MESSAGE
  589. ==============
  590.    Borra un mensaje ya definido.
  591.  
  592. Sintaxis
  593.    DELETE MESSAGE|METHOD NombreMensaje
  594.  
  595. Propósito
  596.    Elimina de la clase actúal NombreMensaje. Es utilizable en clases
  597.    derivadas donde es seguro que no se utilizará, ni en ella ni en sus
  598.    descendientes.
  599.  
  600. Ejemplo
  601.    DELETE MESSAGE Mover
  602.  
  603.  
  604. END CLASS
  605. =========
  606.    Ver ENDCLASS
  607.  
  608.                          -pag. 12-
  609.  
  610.  
  611. ENDCLASS
  612. =======
  613.    Indica que ha finalizado la definición de la clase
  614.  
  615. Sintaxis
  616.    ENDCLASS [NombreClase]
  617.  
  618. Ejemplo
  619.    ENDCLASS Window
  620.  
  621.  
  622.  
  623. METHOD
  624. ======
  625.    Declara un método y sus parámetros
  626.  
  627. Sintaxis
  628.    METHOD [FUNCTION|PROCEDURE] idMétodo( [parámetros] )
  629.  
  630. Propósito
  631.    Al igual que FUNCTION declara una función, METHOD declara un método,
  632.    que no es más que una función asociada a un mensaje.
  633.  
  634.    Las palabras clave FUNCTION o PROCEDURE son opcionales y se incluyen
  635.    por compatibilidad con oClip y otras.
  636.  
  637.    El código del método dispondrá, aparte de las declaradas ya, una
  638.    variable local más: el objeto Self: (abrebiado ::). Este objeto
  639.    representa el actual sobre el que se está ejecutando el método.
  640.  
  641. Ejemplo
  642.    METHOD Mover( nTop, nLeft )
  643.       ::Restaurar()
  644.       ::nBottom += nTop - ::nTop
  645.       ::nRight  += nLeft - ::nLeft
  646.       ::nTop := nTop
  647.       ::nLeft := nLeft
  648.    RETURN ::Abrir()
  649.  
  650.  
  651. PARENT
  652. ======
  653.    Ejecuta un método asociado con un mensaje de la clase padre.
  654.  
  655. Sintaxis
  656.    ::parent:Mensaje( [parámetros] )
  657.  
  658. Descricpión
  659.    ::parent envía Mensaje al objecto actual pero haciendo que se 
  660.    ejecute el método que estaba asociado con Mensaje en la clase padre, 
  661.    no en la actual.
  662.  
  663.    Esto, obviamente, sólo es necesario cuando en la clase Hijo se ha 
  664.    redefinido un mensaje.
  665.  
  666.                          -pag. 13-
  667.  
  668.  
  669. Ejemplo:
  670.    CLASS VentanaSombra FROM Ventana
  671.    .
  672.    .
  673.    MESSAGE Pinta METHOD VNSPinta( aEsquinas )
  674.    END CLASS
  675.  
  676.    METHOD VNSPinta( aEsquinas )
  677.       Sombra( aEsquinas )   //DIbuja una sombra
  678.       ::parent:Pinta( aEsquinas )   //El método padre hace el resto
  679.  
  680.  
  681. SUPER
  682. =====
  683.    Ejecuta un método asociado con un mensaje de la clase padre.
  684.  
  685. Sintaxis
  686.    :Super( [NombreClase] ):Mensaje( [parámetros] )
  687.  
  688. Descripción
  689.    Su función es la misma que la de ::PARENT.  Esta forma es por 
  690.    compatibilidad con SuperClass. Obsérvese que mientras PARENT se 
  691.    antecede de doble dos puntos, Super sólo lo hace con uno.
  692.  
  693.    :Super tiene la ventaja sobre ::parent de que es posible especificar 
  694.    de qué clase se obtiene el método de mensaje. Si [NombreClase] es 
  695.    nulo, buscará el mensaje en la clase padre. Si [NombreClase] existe, 
  696.    lo buscará en ella. Es necesario si invocamos a un método de una 
  697.    clase que no es la primera-padre, es decir, en casos de herencia 
  698.    múltiple donde queremos especificar a qué clase padre nos referimos.
  699.  
  700. Ejemplo
  701.    METHOD VNSPinta( aEsquinas )
  702.       Sombra( aEsquinas )   //DIbuja una sombra
  703.       :super():Pinta( aEsquinas )   //El método padre hace el resto
  704.  
  705.  
  706. QSUPER
  707. ======
  708.    Ejecuta un método asociado con un mensaje de la clase padre.
  709.  
  710. Sintaxis
  711.    :Qsuper( [NombreClase,] VarStatic ):Mensaje( [parámetros] )
  712.  
  713. Descripción
  714.    Su función es exactamente la misma que :Super().
  715.  
  716.    La ventaja es éste método es que ofrece una forma mucho más rápida 
  717.    de ejecutar las llamadas al método. Esto se logra con el uso de una 
  718.    variable estática (VarStatic). La primera vez que es ejecutada, 
  719.    funciona igual que :Super(), pero el resultado de la búsqueda del 
  720.    método, que es lo que más tiempo lleva, se queda almacenado en 
  721.    VarStatic, de forma que en sucesivas llamadas irá mucho más rápido.
  722.  
  723. Ejemplo
  724.    METHOD VNSPinta( aEsquinas )
  725.       STATIC b
  726.       Sombra( aEsquinas )              //Dibuja una sombra
  727.       :Qsuper( b ):Pinta( aEsquinas )   //El método padre hace el resto
  728.  
  729.                          -pag. 14-
  730.  
  731.  
  732. CLASSH
  733. ======
  734.    Mensaje que devuelve el identificador (handle) de la clase
  735.  
  736. Sintaxis
  737.    obj:ClassH   ---> nHandle 
  738.  
  739. Descripción
  740.    ClassH es un mensaje estándar para todas las clases. Retorna el 
  741.    manejador numérico que utiliza Clipper  para identificar la clase.
  742.  
  743. Ejemplo
  744.    if obj1:ClassH == obj2:ClassH
  745.       ? "Obj1 y Obj2 son de la misma clase"
  746.    else
  747.       ? "Obj1 y Obj2 son de distintas clases"
  748.    endif
  749.  
  750.  
  751. CLASSNAME
  752. =========
  753.    Mensaje que devuelve el nombre de la clase.
  754.  
  755. Sintaxis
  756.    obj:ClassName()  --->cNombreClase
  757.  
  758. Descripción
  759.    ClassName es un mensaje estándar para todas las clases. Retorna una 
  760.    cadena de caracteres con el nombre de la clase de "obj".
  761.  
  762. Ejemplo
  763.    Function MiraVentana( oVentana )
  764.       if oVentana:ClassName() == "GET"
  765.      ? "¿Qué hace un objeto Get aquí?"
  766.      RETURN
  767.       endif
  768.  
  769.  
  770.  
  771.  
  772. FUNCIONES.=
  773. ===========
  774.  
  775. OCLONE
  776. ======
  777.    Devuelve un duplicado de un objeto.
  778.  
  779. Sintaxis
  780.    oClone( objeto )   --> oNew
  781.  
  782. Descripción.
  783.    Al igual que aclone() con los arrays, oclone() devuelve un duplicado 
  784.    del objeto. La asignación normal ( oNew := objeto ) hace que oNew 
  785.    sea un "puntero" a "objeto", de forma que si modificamos uno el 
  786.    cambio afecta a ambos. oClone() efectúa un duplicado real.
  787.  
  788.                          -pag. 15-
  789.  
  790.  
  791.    Al igual que aclone() esta copia no es recursiva. Esto quiere decir 
  792.    que si uno de los elementos que contiene el objeto es un array u 
  793.    otro objeto, el nuevo objeto contendrá nuevos punteros al array u 
  794.    objeto, pero éstos siguen siendo el mismo, no se duplican.
  795.  
  796. Ejemplo
  797.    oVentana := Window():New( 2, 2, 10, 40 )
  798.    oVentana2 := oClone( oVentana )
  799.  
  800.  
  801. NEWOBJECT()
  802. ===========
  803.    Devuelve un objeto nuevo sin inicializar.
  804.  
  805. Sintaxis
  806.    NewObject( nHandleClase )  --->oNew
  807.  
  808. Descripción
  809.    NewObject(), que se incluye por compatibilidad con SuperClass, 
  810.    devuelve un objeto no inicializado de la clase que tiene a 
  811.    nHandleClase por identificador.
  812.  
  813. Ejemplo
  814.    FUNCTION DameObjetoVacio( obj )
  815.    RETURN NewObject( obj:ClassH )
  816.  
  817.  
  818. oSAVE
  819. =====
  820.    Graba un objeto en disco.
  821.  
  822. Sintaxis
  823.    oSave( objeto, cNombreFichero )
  824.  
  825. Descripción
  826.    oSave graba un objeto (o cualquier tipo de variable) en disco con el 
  827.    nombre "cNombreFichero", pudiendo después ser recuperado con 
  828.    oLoad().
  829.  
  830.    Las lógicas exepciones a ésto son:
  831.    -Los elementos de tipo CodeBlock
  832.    -Los arrays u objetos doblemente recursivos, p.e.:
  833.       a := { NIL }
  834.       a[ 1 ] := a
  835.    -Las clases estándar de Clipper. En realidad sí pueden ser grabadas, 
  836.    pero no leídas :-). Lo siento.
  837.  
  838. Ejemplo
  839.    oSave( oArbol1, "001.ARB" )
  840.    oSave( "Cadena de caracteres", "PRUEBA.CHR" )
  841.  
  842.  
  843.                          -pag. 16-
  844.  
  845.  
  846. oLOAD
  847. =====
  848.    Lee un objeto del disco
  849.  
  850. Sintaxis
  851.    oLoad( cNombreFichero ) --->objeto
  852.  
  853. Descripción
  854.    oLoad() lee un objeto (o cualquier tipo de variable) desde un 
  855.    fichero en disco con el nombre "cNombreFichero" y lo devuelve como 
  856.    resultado.
  857.  
  858.    Aspectos a tener en cuenta:
  859.    -Lógicamente no se pueden leer elementos del tipo CodeBlock. Si hay 
  860.    grabado alguno, se retorna como un NIL.
  861.    -Para leer un objeto es necesario que antes hayamos tenido en 
  862.    memoria un objeto de la misma clase o alguna de las derivadas. Así 
  863.    que esto no es solución para tener varios objetos grabados en disco 
  864.    e intentar leerlos en un programa que no contiene las definiciones 
  865.    de las clases.
  866.  
  867. Ejemplo
  868.  
  869.    oArb1 := Arbol()  //Arbol es una clase
  870.    oArb1 := oLoad( "001.ARB" )
  871.  
  872.    qout( oLoad( "PRUEBA.CHR" ) )
  873.  
  874.  
  875.  
  876. PSEUDO-COMANDOS
  877. ===============
  878.    Estos son algunos aspectos sintácticos de XClass que, aunque no 
  879.    hacen nada, se incluyen por razones de compatibilidad con otros 
  880.    gestores de clases. Estos son:
  881.  
  882.    en la definición de clases:
  883.    PROTECTED
  884.    EXPORTED
  885.    READ ONLY
  886.  
  887.    PROTECTED METHODS
  888.    PUBLIC METHODS
  889.    PRIVATE METHODS
  890.    Todos ellos se admiten por compatibilidad con SuperClass aunque en 
  891.    XClass 2.0 todos sean variables y métodos públicos. Lo mismo sucede
  892.    con VAR...READONLY o VAR...HIDDEN
  893.  
  894.  
  895.  
  896. DEBUGGER
  897. ========
  898.    XClass ofrece total compatibilidad con el Debugger de Clipper 5.01. 
  899.    No obstante a veces aparece información extraña sobre variables 
  900.    locales cuando se ejecutan ciertos métodos. Si apareciese este 
  901.    efecto, basta incluir la directiva
  902.  
  903.                          -pag. 17-
  904.  
  905.  
  906.    #define DEBUG
  907.  
  908.    o bien compilar con
  909.  
  910.    CLIPPER fichero.prg /DDEBUG
  911.  
  912.  
  913.  
  914. METODOS-PADRE
  915. =============
  916.    Varias veces se ha hecho referencia en este manual a la problemática 
  917.    de los métodos-padre. Llamamos así a los métodos de una clase padre 
  918.    que han sido redefinidos por otros en la clase hijo pero que, no 
  919.    obstante, a veces necesitan ser llamados.
  920.  
  921.    El ejemplo típico es el de una subclase VENTANA_CON_SOMBRA, que 
  922.    redefine el método PINTA para dibujar primero la sombra, pero 
  923.    después lo más cómodo sería ejecutar el método PINTA de la clase 
  924.    padre, que ejecutaría el resto de la tarea.
  925.  
  926.    El primer problema es la velocidad. Ya que Clipper 5.01 no 
  927.    implementa de forma directa la herencia, es necesario utilizar unos 
  928.    sistemas de localización del método padre. Así, en un método donde 
  929.    se necesite una alta velocidad y se ejecute repetidas veces, 
  930.    podremos recurrir a :Qsuper()
  931.  
  932.    El segundo problema es el conflicto de nombres. Si derivamos la 
  933.    clase POPMENU de las clases MENU y VENTANA, puede haber mensajes 
  934.    idénticos en ambas clases padre. Siempre tendrá prioridad aquellos 
  935.    que hallan sido definidos en la primera clase que aparece como 
  936.    heredada, en el siguiente ejemplo sería MENU:
  937.  
  938.    CLASS POPMENU FROM MENU, VENTANA
  939.  
  940.    Si queremos llamar al mensaje PINTA, que existe en MENU y VENTANA, 
  941.    la llamada
  942.    :Super():Pinta()
  943.    ejecutará el PINTA() de la clase MENU, mientras que
  944.    :Super( VENTANA ):Pinta()
  945.    ejecutará el PINTA() de la clase VENTANA.
  946.