Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > OOP
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 11-07-2006
Avatar de Ñuño Martínez
Ñuño Martínez Ñuño Martínez is offline
Moderador
 
Registrado: jul 2006
Ubicación: Ciudad Catedral, Españistán
Posts: 6.000
Poder: 25
Ñuño Martínez Tiene un aura espectacularÑuño Martínez Tiene un aura espectacular
Llamar a método virtual de un objeto pasado como parámetro

He estado buscando en el foro y en Internet pero no he encontrado nada.

Tengo un programa que, simplificando mucho, es el siguiente. (No creo que a nadie le cueste seguirlo)

Código Delphi [-]
PROGRAM base;

TYPE
  CLASE_BASE = CLASS
  PUBLIC
    PROCEDURE Metodo; VIRTUAL;
  END;

  CLASE_HIJA = CLASS (CLASE_BASE)
  PUBLIC
    PROCEDURE Metodo; OVERRIDE;
  END;

  PROCEDURE CLASE_BASE.Metodo;
  BEGIN
    WriteLn ('Llamó a CLASE_BASE');
  END;

  PROCEDURE CLASE_HIJA.Metodo;
  BEGIN
    WriteLn ('Llamó a CLASE_HIJA');
  END;

(* Aquí está el problema.  Es un procedimiento que se va a usar como
   "callback", de ahí que reciba un POINTER. *)
PROCEDURE Procedimiento (Objeto: POINTER);
BEGIN
  WITH CLASE_BASE (Objeto) DO
    Metodo;
END;

VAR
  Objeto: CLASE_BASE;
BEGIN
(* Aquí ponemos en marcha todo. *)
  Objeto := CLASE_HIJA.Create;
{ Simulamos una llamada "callback" }
  Procedimiento ( POINTER (Objeto));
  Objeto.Free;
END.

Como dice el comentario, voy a utilizar un procedimiento como "callback", es decir, que voy a pasar la dirección de dicho procedimiento a una librería ya escrita para que lo llame cuando sea necesario (parecido a la función de procesamiento de mensajes de ventana en Windows).

El problema es que cuando se llama al Procedimiento siempre llama al método de la CLASE_BASE y nunca al de la CLASE_HIJA. ¿Por qué me sucede esto? ¿Cómo puedo hacer que llame al método apropiado?

Última edición por dec fecha: 11-07-2006 a las 16:17:09.
Responder Con Cita
  #2  
Antiguo 11-07-2006
Avatar de Ñuño Martínez
Ñuño Martínez Ñuño Martínez is offline
Moderador
 
Registrado: jul 2006
Ubicación: Ciudad Catedral, Españistán
Posts: 6.000
Poder: 25
Ñuño Martínez Tiene un aura espectacularÑuño Martínez Tiene un aura espectacular
Acabo de comprobar que el ejemplo que he puesto anteriormente no reproduce el error, así que voy a incluir el código completo (no es mucho, pero necesitarán conocer la libería GTK+ y tenerla instalada, por eso no quise adjuntar el código desde el principio). También creo que sé de dónde puede venir el error: del uso de SELF al definir la "señal" dentro de TGTK_OBJECT, pero no se me ocurre otra forma de hacerlo (bueno, sí, utilizando punteros a "PROCEDURE OF CLASS" en campos "On<Evento>" al estilo de la VCL, pero no me parece una forma elegante de enfrentarse al problema).

Una solución sería que alguien conociera una buena envolvente en Objetive Pascal de la librería GTK+, pero las únicas que he encontrado o no me compilan o no siguen el diseño original de dicha librería, a parte de que estaría más orgulloso de mí mismo si la consiguiera hacer yo, claro...
Archivos Adjuntos
Tipo de Archivo: zip miGTK.zip (6,5 KB, 18 visitas)

Última edición por Ñuño Martínez fecha: 11-07-2006 a las 16:55:42.
Responder Con Cita
  #3  
Antiguo 11-07-2006
luisgutierrezb luisgutierrezb is offline
Miembro
 
Registrado: oct 2005
Ubicación: México
Posts: 925
Poder: 19
luisgutierrezb Va por buen camino
y si usas Inherited nombre_metodo ¿?
Responder Con Cita
  #4  
Antiguo 11-07-2006
Avatar de Ñuño Martínez
Ñuño Martínez Ñuño Martínez is offline
Moderador
 
Registrado: jul 2006
Ubicación: Ciudad Catedral, Españistán
Posts: 6.000
Poder: 25
Ñuño Martínez Tiene un aura espectacularÑuño Martínez Tiene un aura espectacular
No, porque quien hace la llamada es un procedimiento que nada tiene que ver con las clases (recibe el objeto como parámetro).

Creo que, después de pensarlo, he encontrado un punto de partida. El siguiente método es el de la clase "base":
Código Delphi [-]
(* TGTK_OBJECT::signal_connect:
 *   Conecta la señal con el procedimiento o función de respuesta
 *   correspondiente. *)
PROCEDURE TGTK_OBJECT.signal_connect (aName: Pgchar; aFunc: TGtkSignalFunc);
BEGIN
  gtk_signal_connect (SELF.GtkObject, aName, aFunc, SELF);
END;

Lo que hace es registrar un procedimiento (pasado en el parámetro aFunc) para que sea utilizado como respuesta al evento 'aName'.

El procedimiento 'gtk_signal_connect' recibe, primero, el puntero al objeto GTK (algo así como el handle de un control Windows), el nombre del evento, el puntero de la función o procedimiento de respuesta del evento (no puede estar dentro de una clase) y un valor que será pasado a la función de respuestas al evento. Yo le paso la referencia al objeto para recuperarlo más tarde. Así, para el evento "destroy" utilizo la siguiente llamada:

Código Delphi [-]
(*** Señales "signals" ***)

(* _signal_destroy_:
 *   Respuesta a la señal "destroy". *)
PROCEDURE _signal_destroy_ (ObjetoGTK: pGtkObject; aData: TGTK_OBJECT); CDECL;
BEGIN
  aData.sDestroy;
END;



(* TGTK_OBJECT::Create:
 *   Crea el objeto, asignando su puntero. *)
CONSTRUCTOR TGTK_OBJECT.Create (aGtkObject: PGtkObject);
BEGIN
  fGtkObject := aGtkObject;
{ Respuesta a las señales. }
WriteLn ('Señales TGTK_OBJECT');
  signal_connect ('destroy', GTK_SIGNAL_FUNC (@_signal_destroy_));
END;

El método 'sDestroy' es un método virtual. El problema está en que, aunque sobrecargue (OVERRIDE) dicho método en una clase hija, el procedimiento '_signal_destroy_' sigue llamando al método de la clase base (en este caso TGTK_OBJECT). Creo que el problema está en utilizar 'SELF' al llamar a 'gtk_signal_connect' pero, ¿de qué otra forma podría hacerlo sino?
Responder Con Cita
  #5  
Antiguo 12-07-2006
Avatar de Ñuño Martínez
Ñuño Martínez Ñuño Martínez is offline
Moderador
 
Registrado: jul 2006
Ubicación: Ciudad Catedral, Españistán
Posts: 6.000
Poder: 25
Ñuño Martínez Tiene un aura espectacularÑuño Martínez Tiene un aura espectacular
Solucionado

Me merezco unos capones por lerdo y tormo. Resulta que el código funciona perfectamente tal como está. ¿Cuál era el problema, entonces? Pues que a la hora de crear el objeto lo creaba de la clase base en lugar de la derivada, y por supuesto que llamaba a los métodos de la clase base...

Espero que después de este error estúpido me permitan continuar participando en el foro.
Responder Con Cita
  #6  
Antiguo 12-07-2006
jam jam is offline
Miembro
 
Registrado: may 2003
Posts: 74
Poder: 21
jam Va por buen camino
Me imagino que conecerás el wrapper de GTK con freepascal. Está bastante avanzado. ¿No te sirven?
__________________
-¿no es usted la hija de un famoso banquero?.
-pues no.
-Perdone, pero por un momento pensé que me había enamorado de usted.
Responder Con Cita
  #7  
Antiguo 12-07-2006
Avatar de Ñuño Martínez
Ñuño Martínez Ñuño Martínez is offline
Moderador
 
Registrado: jul 2006
Ubicación: Ciudad Catedral, Españistán
Posts: 6.000
Poder: 25
Ñuño Martínez Tiene un aura espectacularÑuño Martínez Tiene un aura espectacular
Encontré este en sourceforge y no me gusta. El código fuente es muy raro y no me extraña que le salgan esos bugs que dice la documentación (utiliza un preprocesador para generar el código fuente ). Jamás vi nada igual.

Con la versión que viene en el FreePascal que me bajé (creo que es la última estable) sólo viene una traducción directa de C a Pascal. También viene la FCL (Free Component Library) que, al parecer, se basa en GTK pero tampoco me gusta...

En fin, cuando termine el programa que estoy haciendo tal vez publique mi wrapper para ObjectPascal/Delphi a ver si a alguien más le gusta.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
¿Qué son los métodos virtuales y los métodos de clase? David OOP 4 27-07-2019 23:04:30
Virtual Replay - Repetición Virtual de los Goles del Mundial delphi.com.ar La Taberna 0 26-06-2006 17:15:07
Llamar a un método sin tener instacia. piccolo2101 Varios 5 15-12-2005 10:14:35
Como hacer un teclado virtual Andres_Franco DelphiPACK 2 07-01-2004 09:23:12
¿Cómo puedo llamar al método heredado de una clase que no es el ancestro directo? sarackganda OOP 4 15-12-2003 22:19:49


La franja horaria es GMT +2. Ahora son las 01:00:57.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi