Programación Orientada a Objetos con VFP. Importante para aprender otras tecnologías!

4,183 views
Skip to first unread message

Analyzer

unread,
Sep 19, 2013, 3:33:01 PM9/19/13
to publice...@googlegroups.com
Abro este hilo en especial para el amigo Edgar Acevedo y otros compañeros que como yo se nos ha complicado aprender OOP con VFP, a algunos por la falta de documentación, a otros por la falta de tiempo, y a otros porque quizás no le veíamos gran utilidad a todo esto.

Al ir aprendiendo otros lenguajes como PHP, C#, Vb.net, Javascript, Jquery incluso las CSS (Estilos para las páginas web), te vas dando cuenta de la importancia de captar el tema de la Programación Orientada a Objetos, ya que la mayoría de los llamados "Frameworks" de desarrollo web, trabajan bajo el concepto de clases y objetos.

Si nos interesa el tema de los móviles, definitivamente es un tema que no se puede rehuir si se piensa usar JAVA.

Lo que quiero decir es que sea que estemos pensando quedarnos (no es mi caso, pero sí el de algunos) con VFP hasta el final o pensemos ir aprendiendo otras herramientas, el tema de OOP será un tema esencial y en su caso recurrente en esas otras tecnologías. Noto que saber OOP con Fox puede ser de gran ayuda, para comprender la OOP con otros lenguajes, ya que con Fox parece ser muy lógica mientras que con PHP o incluso Vb.net los conceptos pueden ser un poco más dificiles de comprender.

Hasta ahora, no he encontrado mejor documentación para ese tema que la siguiente:


Manual de Clases en Visual Foxpro 9.0 de Walter R. Ojeda Valiente.


Contiene muchos ejemplos además del manual..


Conceptos básicos de Programación Orientada a Objetos con VFP.

Espero que los enlaces puedan ser de mucha utilidad para quienes aun no manejamos bien el asunto de las clases.

Si gustan también podemos aprovechar este hilo para comentar cualquier duda o aportar cualquier explicación sobre OOP que nos puede ir siendo de interés para aprender.

De mi parte, trataré de ir poniendo información desde 0, para arrancar con el tema.

Saludos!

Analyzer

unread,
Sep 19, 2013, 3:38:52 PM9/19/13
to Comunidad de Visual Foxpro en Español
Comparto esta bonita explicación del maestro Fernando D. Bozzo sobre OOP:

Para entender este tema de las clases tenés que empezar por lo básico, que es entender el código. Luego podés usar los diseñadores que te ayudan a crear las clases de forma más visual, pero el contenido será el mismo, nada más que presentado de otra forma.

Te doy un ejemplo en código y el mismo ejemplo en forma visual (asumo que usás VFP 9).

CÓDIGO:
Create un programa llamado MisClases.prg usando MODIFY COMMAND MisClases desde la ventana de comandos y dentro ponele esto:

DEFINE CLASS ordenador AS CUSTOM
    Ram = "2 GB"

    PROCEDURE obtener_Ram
        RETURN THIS.Ram
    ENDPROC

    PROCEDURE setear_Ram
        LPARAMETERS tcValor
        THIS.Ram = tcValor
    ENDPROC
ENDDEFINE

Ahora, desde la ventana de comandos vamos a instanciar y usar esta clase así, copiando de a una línea por vez:

oo = NEWOBJECT( "ordenador", "MisClases.PRG" )
MESSAGEBOX( oo.obtener_Ram() )   && Te muestra "2 GB"
oo.setear_Ram( "3 GB" )
MESSAGEBOX( oo.obtener_Ram() )   && Te muestra "3 GB"
CLEAR ALL


DISEÑADOR:
Ahora vamos a hacer lo mismo, pero usando el diseñador de clases. En este caso te vas a ahorrar la creación de las líneas DEFINE CLASS y ENDDEFINE y los PROCEDURE/ENDPROC
Elegí el menú File / New / Class y luego el botón New File. Te muestra un cuadro de diálogo con 3 datos:
Class Name ==> escribí ordenador
Based on ==> seleccioná custom
Store in ==> escribí MisClases
Y al final elegí el botón OK. Ya estás viendo el diseñador de clases (la clase es ese rectángulo con unos pequeños cuadrado/circulo/triángulo agrupados y de título "ordenador"). Ya tenemos la clase, ahora le agregamos la propiedad Ram:
Vas al menú Class y elegís New Property, te muestra otro cuadro de diálogo:
Name ==> escribí Ram
Default/Initial value ==> borrá el .F. que tiene y escribí "2 GB" sin las comillas
Luego elegís el botón Add y finalmente el botón Close. Es probable que en la parte derecha veas la ventana de propiedades de la clase con la nueva propiedad Ram. Si no ves esa ventana, la podés abrir usando el menú Window / Properties Window, y te vas al final de todo, donde vas a ver tu nueva propiedad.

Ahora creamos los métodos: Elegí el menú Class / New method, en el cuadro de diálogo que aparece, a la derecha del título "name" escribí obtener_Ram y elegí el botón Add. Vasa ver que en la ventana de propiedades se agrega ese método.
Ahora agregá el método setear_Ram, elegí el botón Add y luego Close.

Una vez cerrado el cuadro de diálogo seguimos con la ventana de propiedades. Hacé doble click en el método "setear_ram" y pegale este código, que es el mismo que usamos antes:

LPARAMETERS tcValor
THIS.Ram = tcValor

y cerrá la ventana del código (o pulsá CTRL + W). Vas a ver que aparece un texto en negrita que dice [User Procedure], lo que indica que ese método tiene código.
Ahora hacemos lo mismo para el otro método: Doble click en "obtener_ram" y pegá este código:

RETURN THIS.Ram

y cerrá la ventana del código (o pulsá CTRL + W). Finalmente cerrá la ventana de la clase que tiene el título "Class designer - misclases.vcx (ordenador)" y cuando te pregunte "Do you want to save changes?" elegís Yes.

Ahora estamos nuevamente en la ventana de comandos. Vamos a instanciar y usar esta clase así, copiando de a una línea por vez:

oo = NEWOBJECT( "ordenador", "MisClases.VCX" ) && Como ves, ahora usamos el VCX que acabás de crear
MESSAGEBOX( oo.obtener_Ram() )   && Te muestra "2 GB"
oo.setear_Ram( "3 GB" )
MESSAGEBOX( oo.obtener_Ram() )   && Te muestra "3 GB"
CLEAR ALL


Listo. Ahora podés ver la diferencia entre crear una clase como un PRG o con el diseñador, que la guarda como VCX (y VCT, ya que son dos archivos)
Espero que te sirva para comenzar.

Para más ejemplos de código podés ver el directorio "Samples" dentro del directorio de instalación de FoxPro, que siempre trajo muchos ejemplos de código para probar, y también tenés la ayudam que es muy buena.




Saludos!

Analyzer

unread,
Sep 19, 2013, 3:41:49 PM9/19/13
to Comunidad de Visual Foxpro en Español
También comparto un dato que me parece interesante acerca de los objetos y clases.

Para ver el código que genera el VFP por debajo cuando uno crea un form desde arriba (de forma interactiva).


1.  Haga click en el menú Tools, y elija Class browser.


2.  Con el ícono de "Open", abra la clase o formulario que desee.

Puede que sea necesario elegir "Form" en el tipo de archivo..


3.  En la barra de íconos a la izquierda del binocular, elija el ícono VIEW CLASS CODE.


Con eso se puede ver toda la definición de clase completa de los objetos de VFP. 

Y tan solo con 2 cosas: el ícono de "Open" y el de "View Class Code", del class browser.

Es como si el mismo VFP te mostrará todos sus secretos ocultos.

Nota. Cuando es una clase, también puede servir ver el código del botón View Parent Code, que viene a la derecha de los eventos del formulario.



Saludos!

Edgar Acevedo

unread,
Sep 19, 2013, 3:43:42 PM9/19/13
to publice...@googlegroups.com
Excelente compilación de material.  Gracias por tomarte tu tiempo para agruparlo.


Edgar Acevedo.

Analyzer

unread,
Sep 19, 2013, 4:13:24 PM9/19/13
to Comunidad de Visual Foxpro en Español
Edgar,

Por nada. Lo que más cuesta a veces es comprender los conceptos, pero es sencillo una vez que se captan.

Por ejemplo, en la mayoría de los lenguajes te vas a encontrar con la práctica de "Instanciar" un objeto.

¿Qué es instanciar?..

Simplemente por medio de una instrucción, generar un objeto a partir de la clase.

Es como si se creara un objeto a partir de las características definidas en la clase, como si a partir de las caracteristicas delineadas en un plano, se creara una casa.

Se percibe por intuición, que se podrían hacer muchas casas(objetos) a partir de ese plano(la clase).

En fox, una vez que se se "definió" la clase o dicho de otra forma, se creó la clase, hay que generar objetos basados en esa clase con la instrucción CreateObject():

oPersona1 = CREATEOBJECT( "Persona" )


Como aparece en uno de los manuales, hasta abajo deberá figurar la definición de clase:

DEFINE CLASS Persona AS CUSTOM
* Agregue propiedades, métodos, etc.
      ENDDEFINE

*Nota. No puede haber código después de la definición de la clase, porque no se ejecutará.


En la mayoría de los otros lenguajes se usaría una instrucción "NEW", que provoca ese "instanciamiento". Por ejemplo en Vb.net:

Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        ' Agregamos un control texto
        Dim txthola As New TextBox

Esa última línea crea un control tipo text llamado txthola (el nuevo objeto instanciado), a partir de una clase tipo Textbox (las llamadas clases "base").

Saludos!

Víctor Hugo Espínola Domínguez

unread,
Sep 19, 2013, 4:27:30 PM9/19/13
to publicesvfoxpro
Hola Analizer

>*Nota. No puede haber código después de la definición de la clase, porque no se ejecutará.

Puede haber más código de definición de otras clases.

Saludos,
Víctor.
Lambaré - Paraguay.

Analyzer

unread,
Sep 19, 2013, 4:43:19 PM9/19/13
to Comunidad de Visual Foxpro en Español
El ejemplo 3 del manual de Walter es bastante didáctico, ya que de él se pueden comprender fácilmente muchas cosas como la herencia.

EJEMPLO03.PRG

* Aquí se define el "alcance" del objeto, en este caso "local".

Local loNuevoSocio

CLEAR

*Aquí se "instancia" o genera un objeto llamado loNuevoSocio, a partir de la clase SOCIO.

loNuevoSocio = CreateObject("SOCIO")

* Aquí se "personaliza" el objeto modificando sus propiedades.

with loNuevoSocio
.cNombre = "Juan"
.cApellido = "Pérez"
.dFechaNacimiento = CtoD("03/01/1980")
.dFechaIngreso = Date()
.MostrarDatos()
.MostrarDatos2()
endwith

*Aquí se "destruye" la instancia de este objeto en la memoria.
Release loNuevoSocio
Return

*Aquí se crea una clase llamada persona basada en las clases de Fox (Custom).

DEFINE CLASS PERSONA AS CUSTOM
cNombre = Space(20)  * Aquí se esta agregando una propiedad
cApellido = Space(20)
dFechaNacimiento = {}
PROCEDURE MostrarDatos     ** Aquí se está agregando un método
? This.cNombre, This.dFechaNacimiento   ** Ese "This" hará referencia al objeto actual
RETURN
ENDDEFINE

*Aquí entiendo que se crea una "subclase" llamada SOCIO que "hereda" las características de la clase en que se basa, en este caso la clase padre "persona".

DEFINE CLASS SOCIO AS PERSONA
dFechaIngreso = {}
PROCEDURE MostrarDatos2
? This.cNombre, This.cApellido, This.dFechaIngreso
RETURN
ENDDEFINE

Si algo está mal en la explicación, pueden corregirlo.. La idea es aprender.

Saludos!

Analyzer

unread,
Sep 19, 2013, 4:56:43 PM9/19/13
to Comunidad de Visual Foxpro en Español
Gracias Víctor Hugo, por la aclaración oportuna.

Cito textualmente el manual de Walter:

Es importante recordar que las definiciones de clases siempre deben escribirse al final del programa. ¿Por qué? porque el código que se escriba después de las definiciones de las clases nunca será ejecutado.

Entonces se refiere a que no puede haber código "normal", sino solo código de "puras clases".

Saludos!

Víctor Enrique Navarro Hoyos

unread,
Sep 19, 2013, 5:30:16 PM9/19/13
to publice...@googlegroups.com
¡¡Buen trabajo!!
Muchas gracias

Victor Navarro
Ing. de Sistemas
Barranquilla, COLOMBIA
3008102508
ICQ 279 364 380
Face: +573008102508
MSN: eres_u...@hotmail.com <deshabilitado>
Mail: eres_u...@yahoo.es
Whatsapp: +573008102508
Skype: eres_un_vago

Víctor Hugo Espínola Domínguez

unread,
Sep 19, 2013, 5:47:41 PM9/19/13
to publicesvfoxpro
Hola Analizer

Walter ya lo dijo en forma implícita:

>Es importante recordar que las definiciones de clases siempre deben escribirse al final del programa. ¿Por qué? >porque el código que se escriba después de las definiciones de las clases nunca será ejecutado.

Puede haber más código de definición de otras clases.

Saludos,
Víctor.
Lambaré - Paraguay.

Analyzer

unread,
Sep 20, 2013, 10:36:47 AM9/20/13
to Comunidad de Visual Foxpro en Español
Otra cosa que puede ser de utilidad es comprender el uso de la palabra "Parent".

El ejemplo No. 7 del manual explica claramente como se usaría y cuál es el concepto de la palabra parent.

Básicamente, el ejemplo ilustra como es posible desde un control, como un botón de comando (la clase "hijo") , alterar las propiedades como el "caption" de la clase "padre", que en este caso es un formulario.

*------------------------------------------------------------------------------------------------------
*--- CLASES EN VISUAL FOXPRO 9.
*--- Walter R. Ojeda Valiente
*--- 02/JUL/2011
*--- Agregándole objetos a un formulario
*------------------------------------------------------------------------------------------------------

Local loForm
  
  loForm = CreateObject("FORM")
  
  with loForm
    .Caption = "Este es el caption original del formulario"
    .AddObject("Boton1", "BotonCAMBIA")
    .AddObject("Boton2", "BotonSALIR")
    .Boton1.Visible = .T.
    .Boton2.Visible = .T.
    .Show()
  endwith
  
  READ EVENTS
  
  Release loForm
  
Return
*
*
DEFINE CLASS BotonCAMBIA AS COMMANDBUTTON
  Caption = "Cambiar título"
  Left    = 20
  PROCEDURE Click
    This.Parent.Caption = "Este es el nuevo caption del formulario"
  ENDPROC
ENDDEFINE
*
*
DEFINE CLASS BotonSALIR AS COMMANDBUTTON
  Caption = "SALIR"
  Left    = 200
  PROCEDURE Click
    CLEAR EVENTS
  ENDPROC
ENDDEFINE
*

Saludos!
Thisparent.PNG

Analyzer

unread,
Sep 21, 2013, 3:06:31 PM9/21/13
to publice...@googlegroups.com
Leyendo información sobre Clases, me encontré con este interesante hilo, donde explica la diferencia entre:

1. Usar Create Object() y usar New Object()
2. Usar un VCX o usar un PRG para guardar clases.

El primer comentario del maestro Víctor Espina es muy esclarecedor:

Viendo hoy el fuente de ActiveVFP me encontre con un uso de NEWOBJECT() que no habia visto nunca.  Yo sabia que NEWOBJECT() se podia usar para instanciar una clase definida en una libreria VCX sin necesidad de cargar dicha libreria en memoria con SET CLASSLIB:

object = NEWOBJECT("miclase","libreria.vcx")

Incluso, se puede instanciar la clase aun cuando la libreria este incluido en un EXE o APP distinto al actual:

object = NEWOBJECT("miclase","libreria.vcx","modulo.exe")

Lo que NO SABIA es que NEWOBJECT() tambien funciona con clases definidas con DEFINE CLASS y almacenadas en un FXP, sin necesidad de cargar el FXP con SET PROCEDURE:

object = NEWOBJECT("miclase","libreria.prg")

Mas de veinte anos conociendo Foxpro y todavia me sorprende con cosas nuevas... increible!

Saludos

Victor Espina


Hilo original en el foro:

NEWO BJECT() con DEFINE CLASS
https://groups.google.com/forum/#!topic/publicesvfoxpro/U79OGlxl44Q


Saludos!

Analyzer

unread,
Sep 21, 2013, 3:23:17 PM9/21/13
to Comunidad de Visual Foxpro en Español
Este enlace explica bien como acceder a los métodos de la clase Padre.

http://www.pablin.com.ar/computer/cursos/vfoxpro/vfpoop02.htm

El Operador ::. Si es observador se habrá percatado que en ejemplo anterior estamos duplicando parte del código del método Imprimir de la clase Persona en el método imprimir la clase Contribuyente, esto no parece muy acertado para ayudar al mantenimiento del código.

En algunos casos queremos sobreescribir totalmente el método de la clase padre, pero en otros casos lo que deseamos en sólo incluir nuevas prestaciones, pero manteniendo el código anterior. Para estos casos se ha creado el operador :: u operador de resolu ción de alcance. Con el podemos hacer referencia al método de una clase superior aun cuando este método se hubiera sobreescrito.

Para hacer uso de este operador debemos indicar el nombre de la clase padre, el operador ::, y el nombre del método. Haciendo uso de este operador podríamos haber escrito la clase Contribuyente de la siguiente forma :

	DEFINE CLASS Contribuyente AS Persona
	  cNIF = ""
	  nBaseImponible = 0
	  cRegimenSS = ""

	  PROCEDURE Imprimir

	    * Llamada al procedimiento
	    * original de la clase Persona
	    Persona::Imprimir() && OPERADOR ::

	    * Resto de impresión
	    ? "Estado civil : " ;
	       + This.cEstadoCivil
	    ? "NIF : " ;
	       + This.cNIF
	    ? "Base Imponible : " ;
	       + STR( This.nBaseImponible )
	    ? "Regimen de la S.S. : " ;
	       + This.cRegimenSS
	  ENDPROC
	ENDDEFINE

Esta característica nos asegura un buen mantenimiento de nuestras clases, pues cualquier modificación en el método de la clase padre, se ve automáticamente reflejado en el método de la clase hija, aunque este sobre escríto el método.



Saludos!

Fernando D. Bozzo

unread,
Sep 21, 2013, 3:25:24 PM9/21/13
to publice...@googlegroups.com
Lo del NewObject instanciando de un PRG creo que se puede hacer desde Foxpro 6, al menos hace varios años que lo uso.

Pero hay un tema de performance que no se debe descuidar: Si se requieren instanciar muchos objetos, CreateObject es mucho más rápido que NewObject.

Saludos.-

Analyzer

unread,
Sep 21, 2013, 3:33:01 PM9/21/13
to Comunidad de Visual Foxpro en Español
También en la ayuda menciona que el CreateObject(), aunque requiere abrir explicitamente el archivo de librerias de clase puede manejar automatización (Word, Excel, etc.)


Saludos!

Analyzer

unread,
Sep 27, 2013, 4:22:11 PM9/27/13
to publice...@googlegroups.com
Otra duda acerca de OOP.

Leo en un libro de Vb.net que existe un método "constructor" que se ejecuta primero al instanciar un objeto.

El método constructor New( )
Toda clase debe tener lo que se denomina un método constructor, que es el primero que se ejecuta cuando es instanciado un objeto de la clase, y en él se escribe el código de inicialización para el objeto.

¿Cuál sería el método constructor en VFP?.. ¿El init?..

¿Hay alguna forma o documentación para ver el orden en que se ejecutan los métodos dentro de una clase?..

Saludos!

Fernando D. Bozzo

unread,
Sep 27, 2013, 5:12:44 PM9/27/13
to publice...@googlegroups.com
Hola Analyzer:

El equivalente en FoxPro supongo que sería el propio CREATEOBJECT() o NEWOBJECT(), ya que es el instancia la clase y crea el objeto.

Saludos.-

Fernando D. Bozzo

unread,
Sep 27, 2013, 5:18:17 PM9/27/13
to publice...@googlegroups.com
Sobre tu segunda pregunta:


"¿Hay alguna forma o documentación para ver el orden en que se ejecutan los métodos dentro de una clase?.."

Seguramente te refieras a los eventos, no a los métodos, y hay bastante documentación sobre eso, tanto en la ayuda local (F1 y buscar "events") como en Internet:

Event sequence in Visual FoxPro:
http://msdn.microsoft.com/en-us/library/620w26ce%28v=vs.80%29.aspx

Firing sequence of Visual FoxPro events:
http://support.microsoft.com/kb/136690/en-us

Events in Visual FoxPro:
http://msdn.microsoft.com/en-us/library/3zz49kdb%28v=vs.80%29.aspx



Saludos.-


El viernes, 27 de septiembre de 2013 22:22:11 UTC+2, Analyzer escribió:

Carlos Miguel FARIAS

unread,
Sep 27, 2013, 8:27:18 PM9/27/13
to Grupo Fox

el método constructor en vfp es el init y el destructor es el destroy salvo en clases empty. el objeto form tiene la particularidad de disparar varios métodos antes de construirse, como el load.
los parámetros que se pasan a un objeto al construirse, son recibidos en el init.
saludos: Miguel, la Pampa (RA)

Analyzer

unread,
Sep 27, 2013, 9:02:12 PM9/27/13
to Comunidad de Visual Foxpro en Español
Fernando D.,

Entiendo perfectamente lo que dice sobre el CreateObject() en relación al New() de .Net

Ambas instrucciones hacen lo mismo: instanciar un objeto a partir de una clase.

Parece que el concepto de constructor aunque como concepto es el mismo en VFP y .Net, tiene diferentes matices.

Por ejemplo, me llama la atención que ese manual diga que hay un método llamado "constructor" que se ejecuta "primero" al instanciar la clase. Supongo que los conceptos son un tanto distintos, pero parece que ese constructor sí es el Init de VFP.

Busqué la palabra constructor en la ayuda de VFP8 (porque está en Español) y en el tema:

Agregar llamadas a la API de Visual FoxPro

Dice en parte:

Para agregar rutinas de la API de Visual FoxPro a su objeto ActiveX 
Use #INCLUDE para incluir el archivo Pro_ext.h junto con otros archivos de encabezado necesarios. 
En el Constructor (método Init) del control, llame a _OCXAPI( ) para inicializar la interfaz para comunicarse con Visual FoxPro mediante este código: 
_OCXAPI(AfxGetInstanceHandle(),DLL_PROCESS_ATTACH);
Incluya llamadas a la API de Visual FoxPro como lo requiera su objeto. 
En el Destructor (método Destroy) del objeto, vuelva a llamar a _OCXAPI( ) para liberar el proceso creado en el Constructor, mediante este código: 
_OCXAPI(AfxGetInstanceHandle(),DLL_PROCESS_DETACH);

Creo que tendré que estudiar un poco más el concepto de "constructor" en .Net porque está confuso aunque si es fácil captar que el New() hace lo mismo que el CreateObject() pero está raro lo que dice ese manual. Debe haber algo más por ahi..



Saludos!

Analyzer

unread,
Sep 27, 2013, 9:05:47 PM9/27/13
to Comunidad de Visual Foxpro en Español
CMF,

Esto parece ser lo que indica la ayuda para VFP, como acabo de indicarle a Fernando.

Definitivamente, pienso que hay algo más complejo en el concepto de constructor en el .Net.

En VFP el concepto está claro y consistente. Seguiré documentándome..

Gracias!


Saludos!

Analyzer

unread,
Sep 27, 2013, 9:08:17 PM9/27/13
to Comunidad de Visual Foxpro en Español
Fernando D.,

Gracias por los enlaces..

Por un momento (por lo del constructor y eso) pensé que la ejecución de los "eventos" era un tanto distinta dentro de una clase, que en el uso sin clases de VFP..

Mis disculpas..


Saludos!
Reply all
Reply to author
Forward
0 new messages