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 04-02-2009
gushynet gushynet is offline
Miembro
 
Registrado: ago 2008
Posts: 26
Poder: 0
gushynet Va por buen camino
Question Saber si un método tiene implementación

Buenas, a ver si alguien me puede orientar un poco: tengo una clase base donde existe un método virtual. De esa clase base desciende una clase que no implementa el método antes mencionado.

Lo que quiero hacer es un procedimiento al cual se le pasa un objeto, de uno de los tipos comentados. El procedimiento debe ejecutar el método pero antes debe averiguar si para ese objeto el método está implementado o no.

Mi pregunta es si se puede saber en tiempo de ejecución si para un objeto dado, un método que ha heredado lo ha vuelto a implementar o usa la implementacion de su ancestro.


Gracias de antemano

Un saludo
Responder Con Cita
  #2  
Antiguo 04-02-2009
poyo poyo is offline
Miembro
 
Registrado: ene 2009
Posts: 47
Poder: 0
poyo Va por buen camino
date una vuelta por este hilo.

Se me ocurre que así podrías comparar los punteros del método... eso sí: tendrías que saber el índice correspondiente.

De todos modos, me parece que NO va a ser posible saber a ciencia cierta si el nuevo método implementado llama o no al método del ancestro mediante "Inherited"...
Responder Con Cita
  #3  
Antiguo 04-02-2009
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.275
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
No se si utilizando RTTI se podría llegar al método.
Busca ayuda sobre MethodAdress y a partir de ahí a ver si accedes a la dirección y si te devuelve algo correcto.
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #4  
Antiguo 05-02-2009
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
¡Hola!

El caso es interesante, porque puede resolverse con algo parecido al código que escribí en el hilo referido por Poyo. Pero ¿estamos hablando de una clase y un método cuyos nombres se conocen de antemano, o es algo más genérico?

Saludos.

Al González.
Responder Con Cita
  #5  
Antiguo 05-02-2009
gushynet gushynet is offline
Miembro
 
Registrado: ago 2008
Posts: 26
Poder: 0
gushynet Va por buen camino
El método se conoce, lo que no se conoce a priori es si el objeto descendiente de la clase base reimplementa el método o sigue usando el de la clase base. La cuestion es que en un punto del programa me gustaria saber si el objeto que estoy tratando tiene reimplementado el metodo que hereda de su ancestro o por el contrario usa el del ancestro, ya que en función de una cosa u otra se ejecuta un codigo distinto.

Saludos
Responder Con Cita
  #6  
Antiguo 05-02-2009
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Hola gushynet,

¿No podrías ampliar un poco el porqué de la necesidad? Quizá esa decisión que mencionas pueda plantearse de otra manera más estándar.

// Saludos
Responder Con Cita
  #7  
Antiguo 05-02-2009
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
¡Hola!

Como dice Román, quizá haya una solución más estándar al problema de fondo (esperamos llegar a conocerlo).

Pero esta noche aproveché un espacio de tiempo para realizar algunos experimentos que dieron como resultado el siguiente código. Funciona bien y en esencia soluciona el problema bajo los términos descritos por Gushynet, aunque no sugeriría que lo empleara sin antes conocer más a detalle el caso que originó ese planteamiento.

Digamos que para mí fue más que nada un ejercicio de aprendizaje y al final el gusto por compartir los resultados.

Código Delphi [-]
implementation

{$R *.dfm}

Type
  // Clase base que declara dos métodos virtuales, uno de ellos abstracto
  TA = Class
    Procedure Proc1; Virtual;
    Procedure Proc2; Virtual; Abstract;
  End;

  // Clase hija que redefine los dos métodos virtuales
  TB = Class (TA)
    Procedure Proc1; Override;
    Procedure Proc2; Override;
  End;

  // Clase hija que no redefine ninguno de los métodos virtuales
  TC = Class (TA)
  End;

Procedure TA.Proc1;
Begin
End;

Procedure TB.Proc1;
Begin
End;

Procedure TB.Proc2;
Begin
End;

{ Función para saber si Obj redefine el método Proc1.  Código para métodos
  virtuales NO abstractos. }
Function RedefineProc1 (Const Obj :TA) :Boolean;
Type
  TMetodo = Procedure Of Object;
Var
  Metodo :TMethod;
Begin
  TMetodo (Metodo) := Obj.Proc1;
  Result := Metodo.Code <> @TA.Proc1;
End;

{ Función para saber si Obj redefine el método Proc2.  Código para métodos
  virtuales abstractos y no abstractos. }
Function RedefineProc2 (Const Obj :TA) :Boolean;
Type
  TMetodo = Procedure Of Object;
Var
  Metodo :TMethod;
  EntradaVMT :Pointer;
Begin
  EntradaVMT := TA;

  Asm
    { De la VMT de TA, obtenemos la entrada que guarda la dirección del
      método Proc2 (cuando el método es abstracto, esa entrada contiene la
      dirección de memoria del procedimiento _AbstractError) }
    Add EntradaVMT, VMTOffset TA.Proc2
  End;

  TMetodo (Metodo) := Obj.Proc2;
  Result := Metodo.Code <> Pointer (EntradaVMT^);
End;

procedure TForm1.Button1Click(Sender: TObject);
Var
  A, B, C :TA;
begin
  { TEMA: Cómo saber si la clase de un objeto redefine un método virtual. }

  A := TA.Create;
  B := TB.Create;
  C := TC.Create;

  // Pruebas con Proc1

  If RedefineProc1 (A) Then
    ShowMessage ('A sí redefine Proc1')
  Else
    ShowMessage ('A no redefine Proc1');

  If RedefineProc1 (B) Then
    ShowMessage ('B sí redefine Proc1')
  Else
    ShowMessage ('B no redefine Proc1');

  If RedefineProc1 (C) Then
    ShowMessage ('C sí redefine Proc1')
  Else
    ShowMessage ('C no redefine Proc1');

  // Pruebas con Proc2

  If RedefineProc2 (A) Then
    ShowMessage ('A sí redefine Proc2')
  Else
    ShowMessage ('A no redefine Proc2');

  If RedefineProc2 (B) Then
    ShowMessage ('B sí redefine Proc2')
  Else
    ShowMessage ('B no redefine Proc2');

  If RedefineProc2 (C) Then
    ShowMessage ('C sí redefine Proc2')
  Else
    ShowMessage ('C no redefine Proc2');

  A.Free;
  B.Free;
  C.Free;
end;

Anexo el programa de ejemplo.

Un abrazo virtual.

Al González.
Archivos Adjuntos
Tipo de Archivo: zip VMTSaberRedefine.zip (4,2 KB, 3 visitas)
Responder Con Cita
  #8  
Antiguo 05-02-2009
gushynet gushynet is offline
Miembro
 
Registrado: ago 2008
Posts: 26
Poder: 0
gushynet Va por buen camino
Question

buenas de nuevo. Lo siento si la pregunta no ha sido todo lo clara, pero mi intención era no hacer muy tedioso y largo el texto de la pregunta, pero visto que ha creado expectación (yo pensaba que era una duda trivial) intentaré explicarme un poco mejor.

La situación es la siguiente:

Tengo la clase TPadre y la clase THijo. TPadre implementa el método 'accion' que es virtual. THijo usa la implementacion de accion que hay en TPadre. Si dado un objeto del cual solo se que es descendiente de TPadre, como puedo averiguar si dicho objeto tiene reimplementado el metodo de TPadre o por el contrario sigue usando el de TPadre.

En definitiva se podria decir que lo que estoy intentanto averiguar es si en la clase THija el metodo accion tiene la clausula override o simplemente no está por estar usando la implementacion de TPadre, pero todo esto en tiempo de ejecucion claro.

En el ejemplo esta TPadre--->THijo, pero la jerarquia puede ser todo lo compleja que se quiera.


Espero que ahora si me haya explicado (es que soy un incomprendido
Si no se entiende entonces si me explayaré todo lo necesario.

Saludos, y gracias por las respuestas recibidas y por las que vendrán
Responder Con Cita
  #9  
Antiguo 05-02-2009
gushynet gushynet is offline
Miembro
 
Registrado: ago 2008
Posts: 26
Poder: 0
gushynet Va por buen camino
Antes que nada pedir disculpas a AI Gonzales por haber respondido antes de leer su mensaje.

Con respecto al ultimo codigo expuesto se me ha pasado por la cabeza la siguiente locura-duda:

si en la clase base el metodo es virtual y en la clase hija no se reimplementa quiere decir que la clase hija usa el mismo metodo que la clase padre. Ahora bien, la pregunta es, ¿usar el mismo significa que es el mismo método, es decir comparten el mismo metodo en memoria, o por el contrario cada objeto tiene una copia del método en memoria aunque sean el mismo?

Esta pregunta surge de otra duda: todo metodo tiene una posicion de inicio en memoria?

Si la respuesta es si, se podrian comparar las posiciones de inicio en memoria de los metodos de TPadre y THijo y averiguar asi si son el mismo metodo o no?


Gracias por la ayuda prestada
Saludos

PD: AI Gonzalez, podrías indicarme alguna pagina, hilo, documentacion en definitiva, sobre algunas cosas del codigo de ejemplo que hiciste, concretamente sobre las funciones redefine ya que hay cosas que no he visto y aunque sospecho lo que pueden hacer preferira no dejarme llevar por la intuicion y confiar en alguien que si este familiarizado con el asunto que estamos tratanto.
Responder Con Cita
  #10  
Antiguo 05-02-2009
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
¡Hola!

Cita:
Empezado por gushynet Ver Mensaje
Tengo la clase TPadre y la clase THijo. TPadre implementa el método 'accion' que es virtual. THijo usa la implementacion de accion que hay en TPadre. Si dado un objeto del cual solo se que es descendiente de TPadre, como puedo averiguar si dicho objeto tiene reimplementado el metodo de TPadre o por el contrario sigue usando el de TPadre.

En definitiva se podria decir que lo que estoy intentanto averiguar es si en la clase THija el metodo accion tiene la clausula override o simplemente no está por estar usando la implementacion de TPadre, pero todo esto en tiempo de ejecucion claro.

En el ejemplo esta TPadre--->THijo, pero la jerarquia puede ser todo lo compleja que se quiera.


Espero que ahora si me haya explicado (es que soy un incomprendido
Si no se entiende entonces si me explayaré todo lo necesario.
Gracias por explicarlo con mayor detenimiento, Gushynet. Pero me parece que es lo mismo que ya dábamos por entendido Román y yo. Nuestra inquietud por pedirte más información de contexto surge de la sospecha de que detrás de todo esto hay otra necesidad o motivación, es decir, que el origen concreto del planteamiento podría atacarse de otra manera.

Pero para profundizar en ello, creo que sería muy útil que nos dieras a conocer al menos un ejemplo real y concreto de esta situación, incluyendo un poco de código (incluso seudo código de cómo lo visualizas ya terminado), algo de la aplicación que estás programando y de cómo fue que te topaste con esta idea.

Vaya, me imagino diciéndonos algo como:
Cita:
Ah, pues mira, la clase en cuestión es TWinControl y el método en cuestión es AdjustClientRect, el cual es redefinido sólo por unas cuantas clases derivadas, como TCustomPanel y TScrollingWinControl, pero no así por la gran mayoría de descendientes (TButton, TEdit, etc). Entonces tengo un proceso que cuando el usuario se posiciona en un control (sea botón, edit, etc.) quiero que se valide que...y para ello le envío este objeto como parámetro a esta función [código de la función] para que haga esto, pero valide aquello, porque de esta forma me aseguro de que cuando..., etc., etc.
O bien:
Cita:
Estoy creando una jerarquía de clases, de la siguiente manera. Tengo el método virtual X que sirve para...y entonces lo redefino aquí y allá, de tal manera que haga esto otro...pero al hacer este proceso requiero validar si el método está redefinido, ya que cuando no lo está, el programa podrá realizar tal cosa, pero si estuviera redefinido me causa este problema..., el cual podría solucionarse si primero verifico si hay redefinición o no, y con eso podría poner este If para que el código de mi rutina quede así...



Cita:
Empezado por gushynet Ver Mensaje
Antes que nada pedir disculpas a AI Gonzales por haber respondido antes de leer su mensaje.
No te preocupes, ya estoy ligeramente acostumbrado a eso, y también a que confundan mi nombre (Al-berto González).

Cita:
Empezado por gushynet Ver Mensaje
Con respecto al ultimo codigo expuesto se me ha pasado por la cabeza la siguiente locura-duda:

si en la clase base el metodo es virtual y en la clase hija no se reimplementa quiere decir que la clase hija usa el mismo metodo que la clase padre. Ahora bien, la pregunta es, ¿usar el mismo significa que es el mismo método, es decir comparten el mismo metodo en memoria, o por el contrario cada objeto tiene una copia del método en memoria aunque sean el mismo?
Es el mismo método compartido (no se crean copias).

Cita:
Empezado por gushynet Ver Mensaje
Esta pregunta surge de otra duda: todo metodo tiene una posicion de inicio en memoria?

Si la respuesta es si, se podrian comparar las posiciones de inicio en memoria de los metodos de TPadre y THijo y averiguar asi si son el mismo metodo o no?
En efecto, eso mismo es lo que hago en las funciones RedefineProc1 y RedefineProc2 que puse anteriormente.
Código Delphi [-]
  { Devuelve True si el método Obj.Proc1 tiene una dirección 
    de memoria  diferente que el método TA.Proc1 }
  TMetodo (Metodo) := Obj.Proc1;
  Result := Metodo.Code <> @TA.Proc1;
Código Delphi [-]
  { Devuelve True si el método Obj.Proc2 tiene una dirección de memoria
    diferente que la indicada por la VMT de la clase TA }
  TMetodo (Metodo) := Obj.Proc2;
  Result := Metodo.Code <> Pointer (EntradaVMT^);


Cita:
Empezado por gushynet Ver Mensaje
PD: Al Gonzalez, podrías indicarme alguna pagina, hilo, documentacion en definitiva, sobre algunas cosas del codigo de ejemplo que hiciste, concretamente sobre las funciones redefine ya que hay cosas que no he visto y aunque sospecho lo que pueden hacer preferira no dejarme llevar por la intuicion y confiar en alguien que si este familiarizado con el asunto que estamos tratanto.
La primera fuente de información que recomiendo es la propia ayuda de Delphi, donde hay algunos temas que hablan de la VMT y del operador VMTOffset. Y el hilo que te recomendó Poyo más arriba trata sobre esos mismos temas. Igualmente está la opción de búsqueda de este estupendo foro, así como el propio Google.

He creado las funciones Redefine con conocimiento de causa, y el algoritmo que utilizo en RedefineProc2 es totalmente seguro para cualquier método virtual, incluso si éste fuese abstracto.

Si tienes dudas sobre lo que hacen algunas partes o sentencias concretas del código que escribí, exprésalas con confianza. Pero reitero la invitación que te hago al principio de este mensaje (exponer el caso que da origen a la necesidad planteada).

Un saludo.

Al González.

Última edición por Al González fecha: 05-02-2009 a las 18:16:14.
Responder Con Cita
  #11  
Antiguo 05-02-2009
[coso] coso is offline
Miembro Premium
 
Registrado: may 2008
Ubicación: Girona
Posts: 1.678
Poder: 0
coso Va por buen camino
Cita:
No se si utilizando RTTI se podría llegar al método.
Busca ayuda sobre MethodAdress y a partir de ahí a ver si accedes a la dirección y si te devuelve algo correcto.
Cita:
Empezado por gushynet
Esta pregunta surge de otra duda: todo metodo tiene una posicion de inicio en memoria?

Si la respuesta es si, se podrian comparar las posiciones de inicio en memoria de los metodos de TPadre y THijo y averiguar asi si son el mismo metodo o no?
me da que si usas methodaddress de una clase y luego de otra, o bien haciendo casting del mismo objeto, y comparas, ya lo tendrias resuelto. saludos.
Responder Con Cita
  #12  
Antiguo 05-02-2009
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Cita:
Empezado por coso Ver Mensaje
me da que si usas methodaddress de una clase y luego de otra, o bien haciendo casting del mismo objeto, y comparas, ya lo tendrias resuelto. saludos.
El problema con MethodAddress es que sólo funciona con métodos publicados:

Cita:
Empezado por Ayuda de Delphi
If Name does not specify a published method for the object, MethodAddress returns nil
Responder Con Cita
  #13  
Antiguo 05-02-2009
poyo poyo is offline
Miembro
 
Registrado: ene 2009
Posts: 47
Poder: 0
poyo Va por buen camino
Bueno, actualicé eso que veníamos hablando en el otro hilo de las VMT y actualicé el RTTIUtils.pas y lo subí al FTP (en Delphi-Win32/Recursos):

http://www.terawiki.clubdelphi.com/a.../RttiUtils.zip

Bueno, además de lo que estaba, le agregué una función que salió de esta conversación. Es la siguiente:

function IsOverrideMethod(AClass, Ancestor: TClass; MethodIndex: Integer ): boolean;

Adentro se chequea que los argumentos sean válidos y luego Itera por la jerarquía de herencias...
mmmm..... ahora que lo pienso a lo mejor está de más eso...
no sé... bué... ya está, luego veremos.

Ejemplo de Uso:

Código Delphi [-]
TPadre = class (TObject)
   procedure a; virtual; abstract;
   procedure b; virtual;
 end;

 THijoA = class (TPadre)
   procedure a; override;
 end;

 THijoB = class (TPadre)
   procedure b; override;
 end;

 THijoC = class (THijoB)
   procedure a; override;
   procedure b; override;
 end;

 THijoD = class (THijoC)
 end;

 THijoE = class (TPadre)
 end;

 THijoF = class (THijoD)
   procedure a; override;
 end;

 THijoG = class (THijoE)
 end;

 THijoH = class (THijoG)
 end;

implementation

uses 
  rttiutils;

procedure TPadre.b;
begin
end;

procedure THijoA.a;
begin
end;

procedure THijoB.b;
begin
end;

procedure THijoC.a;
begin
end;

procedure THijoC.b;
begin
end;

procedure THijoF.a;
begin
end;

procedure check(AClass: TClass);
begin
  if IsOverrideMethod(AClass,TPadre,0) then
    Showmessage(Aclass.ClassName + ': Index 0 = Override!');
  if IsOverrideMethod(AClass,TPadre,1) then
    Showmessage(Aclass.ClassName + ': Index 1 = Override!');
end;


procedure TForm1.FormCreate(Sender: TObject);
begin
  Check(THijoA);
  Check(THijoB);
  Check(THijoC);
  Check(THijoD);
  Check(THijoE);
  Check(THijoF);
  Check(THijoG);
  Check(THijoH);
end;

Se escuchan comentarios, sugerencias y derivadas
Responder Con Cita
  #14  
Antiguo 06-02-2009
gushynet gushynet is offline
Miembro
 
Registrado: ago 2008
Posts: 26
Poder: 0
gushynet Va por buen camino
Hola de nuevo. Voy a intentar explicar lo que estoy haciendo.

Me he creado una clase llamada TUniverso. Esta clase es la clase base a partir de la cual heredan todas las posibles clases que necesite para mis aplicaciones.

Por otro lado tenemos una jerarquia de contenedores cuya clase base es TContenedor y desciende directamente de TUniverso.

TUniverso tiene una serie de operaciones : asignar, duplicar, comparar,EsMayor,...

La cuestion es que todos los objetos que haga son descendientes de TUniverso, por lo que tambien se podran usar los métodos antes descritos.

La gracia del asunto es que he usado RTTI en TUniverso de forma que no se tenga que implementar en las clases que te hagas las funciones tipicas de comparar dos objetos, asignar un objeto a otro,.....

Todo esto funciona para las propiedades publicadas claro.

Por otro lado tenemos la jerarquia contenedor. Estos contenedores guardan cosas del tipo TUniverso o descendiente. Esta jerarquia de contenedores tiene contenedores para guardar elementos del mismo tipo, tipos distintos e incluso elementos repetidos. Hay listas,colas,pilas,arboles,tablas hash,....


Tambien he implementado funciones de E/S para escribir y leer objetos desde fichero.


En definitiva lo que queria hacer era una jerarquia de contenedores genericos. La unica condicion que se impone es que los objetos deben descender directa o indirectamente de TUniverso.

Ahora estoy con las operaciones de E/S.
La forma en que escribo el objeto en disco es igual para objetos simples o complejos. Entiendo un objeto complejo como uno que ademas de tener propiedades simples,enteras,caracteres,....tiene propiedades de tipo objeto, como los contenedores que explique antes.

Dentro de las operaciones de E/S hay dos métodos abstractos (llamemosre EscribirRegistro y LeerRegistro cuya implementacion se deja para el usuario que crea una clase a partir de TUniverso. Razón de estos métodos:

Entiendo que al ahora de guardar un objeto en memoria lo normal es crearse un tipo de registro que albergue las propiedades del objeto que nos interesa guardar. Los métodos del parrafo anterior hacen eso, escribe o lee el registro equivante del objeto en el fichero.

Como no todas las clases de TUniverso necesitan implementar las funcionalidades de E/S puede que haya clases derivadas de TUniverso que no implementen LeerRegistro y EscribirRegistro.

Existe una funcion llamada AddToFile que añade el objeto actual al fichero. Esta funcion es virtual. En TUniverso se implementa de una manera, la cual sirve para objetos simples. Pero en TContenedor cambia la implementacion al ser el objeto un contenedor.

Estoy en un punto en el que estoy insertando unos objetos en un fichero. Este fichero (no lo he dicho) tiene informacion de control para poder localizar los objetos. El problema que tengo es que dentro del procedimiento en un punto debo saber si el objeto que estoy tratando ha cambiado la implementacion de AddToFile o no, ya que la informacion de control que guarde depende de ello.

A parte de la solucion que consiga, la verdad es que me gustaria saber si es posible sacar este tipo de informacion de un objeto.




Pues ya esta, realmente no es como me hubiera gustado explicarlo, pero espero que ahora el contexto del problema este mas claro


PD: de nuevo disculpas por mi mania de responder a los mensajes por el final, ya que se puede dar el caso de que hayan dado una solucion y yo sigo engordando el hilo.

Saludos y gracias por la ayuda que me estan brindando.
Responder Con Cita
  #15  
Antiguo 06-02-2009
gushynet gushynet is offline
Miembro
 
Registrado: ago 2008
Posts: 26
Poder: 0
gushynet Va por buen camino
Una duda que no merece respuesta pero para las horas muertas o para cuando estas bloqueao y no te sale el codigo, da mucho de si:

en que leguaje esta hecho matrix? en VB, delphi, BASIC,.... y si esta hecho VB quiere decir que microsoft esta detras de matrix?

Esto es lo que pasa cuando se esta hasta altas horas de la noche intentadando domar a la bestia de transistores, las dudas empiezan a degradarse
Responder Con Cita
  #16  
Antiguo 06-02-2009
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Gracias por las aclaraciones.

Pues creo que puede servirte perfectamente una función como RedefineProc2. ¿Ya lo probaste?

Aunque no sé si sea la mejor manera de atacar el problema (tendría que ver una muestra de tu código para intentar idear otra forma de resolverlo). Pero de que te funcionará, funcionará.

Si pudieras plasmar lo que has dicho en una jerarquía simplificada de tres o cuatro clases con unos pocos métodos y sentencias esenciales, sería estupendo.
Responder Con Cita
  #17  
Antiguo 07-02-2009
gushynet gushynet is offline
Miembro
 
Registrado: ago 2008
Posts: 26
Poder: 0
gushynet Va por buen camino
Hola, pues gracias a las aportaciones de todos los que os habeis interesado por el tema ya se por donde van los tiros.

AL Gonzales (ahora si lo escribi bien ) no he probado el codigo, mas que nada porque prefiero primero entender bien como funciona el tema de la tabla virtual y realizar mi propio codigo ya que si no no se aprende . De todas formas si a alguien le interesa lo que estoy haciendo no tiene nada mas que pedirme el codigo. Probablemente tendra algunos errores (poco optimizado o nada) pero creo que es una buena manera de conocer un poco las RTTI, asi que si alguien lo quiere....


Otra duda: el uso de las RTTI merman el rendimiento de una aplicación? la duda viene de que las funciones RTTI entiendo que tienen que navegar por la jerarquia de clases y eso debe ser desde un punto de vista computacional muy costoso? estoy en lo cierto?

Y otra pregunta mas: con las RTTI he conseguido informacion sólo sobre propiades de la seccion published. Se puede ir mas lejos y poder conseguir en tiempo de ejecucion informacion sobre propiedades que esten en las otras secciones?

e informacion sobre variables?

por lo que he visto solo se permite para propiedades (y no variables) que esten declaradas en published, pero teniendo en cuenta la falta de documentacion sobre las RTTI a lo mejor si es posible obtener informacion de cualquier componente, sea simple o no, de un objeto.

Gracias por la información.
Un saludo.

PD: una curiosidad, ¿cuantas horas dedicais, en vuestro tiempo libre, a delphiar, ya sea porque os estais haciendo una aplicacion, por probar caracteristicas del lenguaje o entorno, porque para ustedes programar es como para un pintor hacer un cuadro,....
Responder Con Cita
  #18  
Antiguo 07-02-2009
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Cita:
Empezado por gushynet Ver Mensaje
AL Gonzales (ahora si lo escribi bien )...
No, pero ya vas mejorando.


Cita:
Empezado por gushynet Ver Mensaje
no he probado el codigo, mas que nada porque prefiero primero entender bien como funciona el tema de la tabla virtual y realizar mi propio codigo ya que si no no se aprende
Es bueno que al final uno escriba o al menos comprenda todo el código que da solución a un problema, pero empezar por hacer pruebas con lo ya existente no me parece nada desventajoso, al contrario, es una forma muy buena de aprender.

Vuelvo a poner la función que da solución al problema que planteas:
Código Delphi [-]
{ Función para saber si Obj redefine el método Proc2.  Código para métodos
  virtuales abstractos y no abstractos. }
Function RedefineProc2 (Const Obj :TA) :Boolean;
Type
  TMetodo = Procedure Of Object;
Var
  Metodo :TMethod;
  EntradaVMT :Pointer;
Begin
  EntradaVMT := TA;

  Asm
    { De la VMT de TA, obtenemos la entrada que guarda la dirección del
      método Proc2 (cuando el método es abstracto, esa entrada contiene la
      dirección de memoria del procedimiento _AbstractError) }
    Add EntradaVMT, VMTOffset TA.Proc2
  End;

  TMetodo (Metodo) := Obj.Proc2;
  Result := Metodo.Code <> Pointer (EntradaVMT^);
End;
Donde dice Proc2, sólo debes poner el nombre del método en cuestión, y donde dice TA, el nombre de la clase base en cuestión. Por favor, pregunta por los elementos que te resulten desconocidos o confusos.


Cita:
Empezado por gushynet Ver Mensaje
De todas formas si a alguien le interesa lo que estoy haciendo no tiene nada mas que pedirme el codigo. Probablemente tendra algunos errores (poco optimizado o nada) pero creo que es una buena manera de conocer un poco las RTTI, asi que si alguien lo quiere...
Yo me apunto, en mi perfil está mi correo. Pero creo que sería mejor subirlo como archivo anexo, o al menos publicar las partes esenciales entre etiquetas "Delphi" dentro del mismo hilo, para que todo mundo pueda verlo sin mayor protocolo.


Cita:
Empezado por gushynet Ver Mensaje
el uso de las RTTI merman el rendimiento de una aplicación? la duda viene de que las funciones RTTI entiendo que tienen que navegar por la jerarquia de clases y eso debe ser desde un punto de vista computacional muy costoso? estoy en lo cierto?...
No. O al menos depende de qué información se la que consultes. Para lectura y comparaciones de punteros, como las anteriores, el consumo adicional de recursos no es significativo. Pero en el caso de propiedades publicadas que haya que consultar por su nombre expresado en un String, sí puede ser mayor. Sin embargo, al final de cuentas de penderá de cada situación en particular.


Cita:
Empezado por gushynet Ver Mensaje
con las RTTI he conseguido informacion sólo sobre propiades de la seccion published. Se puede ir mas lejos y poder conseguir en tiempo de ejecucion informacion sobre propiedades que esten en las otras secciones?

e informacion sobre variables?

por lo que he visto solo se permite para propiedades (y no variables) que esten declaradas en published, pero teniendo en cuenta la falta de documentacion sobre las RTTI a lo mejor si es posible obtener informacion de cualquier componente, sea simple o no, de un objeto.
En efecto, las propiedades deben ser publicadas (estar declaradas en la sección Published), pero además es necesario que la clase sea compilada bajo la directiva {$M+} (o su equivalente {$TypeInfo On}), o descienda de una clase que haya sido compilada con esa directiva. Es el caso, por ejemplo, de todos los derivados de TPersistent, cuya declaración dentro de la unidad Classes.pas (Delphi 7) es:
Código Delphi [-]
{$M+}

  TPersistent = class(TObject)
  private
    procedure AssignError(Source: TPersistent);
  protected
    procedure AssignTo(Dest: TPersistent); virtual;
    procedure DefineProperties(Filer: TFiler); virtual;
    function  GetOwner: TPersistent; dynamic;
  public
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); virtual;
    function  GetNamePath: string; dynamic;
  end;

{$M-}
Así mismo opté por declarar una clase recientemente en este otro caso, para que el compilador me generara información RTTI de una propiedad (ya que no basta que la propiedad sea publicada): http://www.clubdelphi.com/foros/show...6&postcount=12

Esto es lo que dice la ayuda sobre esa directiva:
Cita:
Type Switch

Syntax {$M+} or {$M-}
{$TYPEINFO ON} or {$TYPEINFO OFF}

Default {$M-}
{$TYPEINFO OFF}
Scope Local

The $M switch directive controls generation of runtime type information (RTTI). When a class is declared in the {$M+} state, or is derived from a class that was declared in the {$M+} state, the compiler generates runtime type information for fields, methods, and properties that are declared in a published section. If a class is declared in the {$M-} state, and is not derived from a class that was declared in the {$M+} state, published sections are not allowed in the class. Note that if a class is forward declared, the first declaration of the class must be declared with the $M switch.

When the $M switch is used to declare an interface, the compiler generates runtime type information for all properties and methods. That is, for interfaces, all members are treated as if they were published.

Note: The TPersistent class defined in the Classes unit of the component library is declared in the {$M+} state, so any class derived from TPersistent will have RTTI generated for its published sections. The component library uses the runtime type information generated for published sections to access the values of a component's properties when saving or loading form files. Furthermore, the IDE uses a component's runtime type information to determine the list of properties to show in the Object Inspector.

Note: The IInvokable interface defined in the System unit is declared in the {$M+} state, so any interface derived from IInvokable will have RTTI generated. The routines in the IntfInfo unit can be used to retrieved the RTTI.

There is seldom, if ever, any need for an application to directly use the $M compiler switch.
Cabe mencionar que Borland hace una sutil separación entre el término RTTI y otros que a veces asociamos con él, como VMT. Aunque en términos generales todo es Run Time Type Information (RTTI), la ayuda de Delphi emplea el término RTTI para referirse principalmente a la información que describe las partes publicadas de las clases. Mucha de esa información es obtenida con las funciones de la unidad TypInfo, y su origen se remonta a la primera versión de Delphi, para fines de almacenamiento y lectura de los componentes en los archivos DFM. Mecanismos de streaming que siguen vigentes.

Por otra parte, la Tabla de Métodos Virtuales (VMT) existe desde que Turbo Pascal vino a proponer destacadamente la programación orientada a objetos. Ya desde entonces Borland había diseñado una ingeniosa forma de guardar apuntadores a los métodos que podrían ser redefinidos (reimplementados) de una clase a otra dentro de la jerarquía. De tal forma que cada clase es en realidad su VMT, una tabla que la describe y que no sólo guarda punteros a métodos virtuales, sino una cantidad significativa de "meta código" adicional.

Estas VMTs y la información que contienen no dependen de si la clase está compilada con la directiva $TypeInfo o no, su información comprende elementos privados (Private), protegidos (Protected), públicos (Public) y publicados (Published). Pero algo de saber es que no guarda detalle de todos ellos, sino nada más de los que son "clave" para realizar ciertas tareas, como por ejemplo la finalización de campos ("variables" del objeto) que usan contadores de referencia, como es el caso de los campos de tipo String.


Cita:
Empezado por gushynet Ver Mensaje
PD: una curiosidad, ¿cuantas horas dedicais, en vuestro tiempo libre, a delphiar, ya sea porque os estais haciendo una aplicacion, por probar caracteristicas del lenguaje o entorno, porque para ustedes programar es como para un pintor hacer un cuadro,....
En mi caso, el tiempo libre es cuando juego baloncesto, leo un libro por gusto, doy un paseo por el parque o veo un filme. Todo lo que hago con Delphi, incluyendo el ayudar a otros, lo considero una responsabilidad, que asumo con gusto, claro.

Un abrazo en tiempo de ejecución.

Al González.

Última edición por Al González fecha: 07-02-2009 a las 22:19:49.
Responder Con Cita
  #19  
Antiguo 08-02-2009
gushynet gushynet is offline
Miembro
 
Registrado: ago 2008
Posts: 26
Poder: 0
gushynet Va por buen camino
Buenas, antes de poner el codigo, una preguna mas: a lo largo de las versiones, delphi ha sufrido muchas modificaciones en las RTTI y el funcionamiento de la VTM, de forma que es complejo desde el punto de vista de la compatibilidad tener un codigo RTTI que sirva para distintas versiones de delphi?, la pregunta viene de que estoy haciendo algo generico pero que me sirva para cualquier version de delphi, pero si la situacion es (no lo se) que para cada version de delphi han salido modificaciones en las RTTI y VMT de forma que hace imposible la compatibilidad usando RTTI pues me llevaria un palo.


Saludos
Responder Con Cita
  #20  
Antiguo 08-02-2009
gushynet gushynet is offline
Miembro
 
Registrado: ago 2008
Posts: 26
Poder: 0
gushynet Va por buen camino
Aqui pongo los dos archivos basicos:

- TUniverso , es la clase base de la jerarquia que estoy haciendo--- aunque se llama TUniversoE_S.pas porque habia cambiado los metodos de E/S. De hecho esa parte no la he terminado porque me tropeze con la duda motivo de este hilo en el foro. Aunque podria haber continuado, encontre la duda interesante y deje un poco de lado lo que tenia entre manos para entender un poco las VTM. Por eso a los metodos de E/S mejor no hacerles caso

- Tipos --- define una serie de tipos de datos.


Saludos.


PD: ahora a machacar el codigo
Archivos Adjuntos
Tipo de Archivo: zip TUniverso.zip (9,4 KB, 3 visitas)
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
Saber que aplicacion tiene el foco Omega Varios 3 13-07-2008 17:36:01
Sobreescribir método Paint y saber coordenadas a refrescar Lord Delfos Gráficos 3 05-03-2008 13:48:28
saber si un field tiene el foco salvanano Conexión con bases de datos 0 08-05-2007 16:22:48
Como saber los dias que tiene un mes?? alfredosg19 Varios 3 06-03-2005 12:56:12
Saber si la Variable tiene letras cmgenny Varios 1 11-05-2004 08:00:59


La franja horaria es GMT +2. Ahora son las 12:50:30.


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