30 de agosto de 2016

Herencia y Polimorfismo con Visual FoxPro

Una de las ventajas que nos dá el uso de clases es el ahorro de programación y el mantenimiento centralizado de códigos que antes podían estár regados (y repetidos) en tu aplicación. Es sencillo, tener tu código lo más general posible, ésto se hace con el uso de propiedades y métodos personalizados por medio de parámetros. Es decir, puede que en cierto lugar establezcas por ejemplo, la tabla base en la que trabajarás, y después, aplicarle métodos con parámetros. Esto es con respecto a herencia, para tratar de que lo que ya escribiste, te sirva en más ocasiones.

Otra función de las clases, es dejar que éstas hagan el código genérico, y después de ello, aplicarle el código específico, esto se hace con la función DoDefault() y el comando NODEFAULT... A continuación un pequeño ejemplo:
oForm = CREATEOBJECT("MyForm")
oForm.SHow(1)
DEFINE CLASS MyForm AS cAbstractForm
   cFormName = "Client Form"
   PROCEDURE cmdAceptar.Click
      DODEFAULT()
      ***** Procedimiento despues de tu codigo base
      MESSAGEBOX("MyForm.Class Message")
   ENDPROC
   PROCEDURE DoAction
     LPARAMETERS tcAction
        MESSAGEBOX("Codigo antes de...")
        DODEFAULT(tcAction)
   ENDPROC     
   PROCEDURE DoExitValidation
      IF DODEFAULT()
         lcMessage = "Reconfirma que quiere salir"
         RETURN (MESSAGEBOX(lcMessage,4+32,this.cFormName)==6)
      ELSE
         RETURN .F.
      ENDIF
   ENDPROC   
ENDDEFINE

DEFINE CLASS cAbstractForm AS FORM
  cExitMessage = "Salir del Formulario"
  ADD OBJECT cmdAceptar AS CommandButton ;
     WITH Top = 200, Left = 150, Caption = "Aceptar",;
          Height = 35
  ADD OBJECT cmdSalir AS CommandButton ;
     WITH Top = 200, Left = 250, Caption = "Salir",;
          Height = 35    
  PROCEDURE cmdAceptar.Click
      Thisform.doAction("Aceptar")
  ENDPROC            
  PROCEDURE cmdSalir.Click
      Thisform.DoAction("Salir")
  ENDPROC
  PROCEDURE DoAction
    LPARAMETERS tcAction
       DO CASE 
          CASE tcAction = "Aceptar"
              *** Simular acción de aceptar
             MESSAGEBOX(tcAction)
          CASE tcAction = "Salir"
             IF  This.DoExitValidation()
                 *** Si ejecutó correctamente su validación, salir del formulario
               This.Release()
             ENDIF
          OTHERWISE 
             MESSAGEBOX("UnHandled Message")   
       ENDCASE        
  ENDPROC
  PROCEDURE DoExitValidation
     RETURN (MESSAGEBOX(this.cExitMessage,4+32,"eSoft Msg") = 6)
  ENDPRO
  PROCEDURE QueryUnload
     IF This.DoExitValidation()
       *** Dejar que haga lo suyo por defecto, salir del form
        DODEFAULT()
     ELSE
        *** Inhibir el comportamiento normal, evita que se cierre el Formulario.
        NODEFAULT
     ENDIF
  ENDPROC
ENDDEFINE
Copia el código anterior, pégalo en tu Command Window, seleccionalo en tu ventana de comandos y presiona ENTER, verás en ejecución un Formulario sencillo, que no tiene más que dos botones uno de aceptar y salir, veamos que es lo que hemos hecho ( y mira que no es poco y quizás te enrede mas...)

He creado una clase abstracta basada en Formulario, en ella se tiene un método general, llamado DoAction, el cual es llamado por los eventos Click de los botones de comando, pasando el parámetro de que acción realizará. También he tenido un método llamado DoExitValidation, éste método se supone hará alguna validación antes de querer salir del formulario, ya sea presionando el botón Salir o haciendo click en el botón de cerrar (esquina superior derecha de todos los formularios), o presionando CTRL+F4, se te das cuenta, el método DoAction al darle como parámetro "Salir" mandará a llamar el método doExitValidation... También tengo un código genérico para el momento de salir, implementado en el evento QueryUnload, mismo que dependerá de DoExitValidation...

Con respecto a nuestra clase heredada de cAbstractForm, le llamamos MyForm, en ella se hace la implementación de todo lo que hemos hecho en la clase base, he puesto varios MessageBox para que se vea el trayecto de cómo se ejecutan las cosas, observemos qué he hecho en nuestras herencias...

MyForm::cmdAceptar.Click() -> Hago que se ejecute cualquiera que sea el código en la clase base, después, ejecuto lo que deseo.

MyForm::doAction() -> Tambien ejecuto código antes de, después hago que se ejecute lo necesario, pasando a la clase base, el parámetro necesario, nótese que ésto afecta el qué se ejecuta en los eventos Click de cmdAceptar y cmdSalir.

MyForm::DoExitValidation() -> Esto es lo más interesante, hago que se ejecute el método base, de ahí, tomo el valor retornado por AbstracForm::DoExitValidation y ejecuto código extra, el cual cambiará el comportamiento de el formulario MyForm, pero no tendrá consecuencias con respecto a lo que necesita el método cAbstractForm::QueryUnload y cAbstractForm::doAction.Salir ya que retorno el mismo tipo de datos...

Así pues, ahi tienes un pequeño ejemplo minimalista de cómo darle herencia y polimorfismo. Espero te sirva.

Espartaco Palma Martínez

1 comentario :