Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Saber si un método tiene implementación (https://www.clubdelphi.com/foros/showthread.php?t=63235)

Al González 08-02-2009 20:52:29

Cita:

Empezado por gushynet (Mensaje 337469)
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...

Al menos en Win32, la mayoría de esas modificaciones han sido meras ampliaciones que conservan compatibilidad hacia atrás. Además por eso mismo introdujeron el operador VMTOffset que utilizo en el ejemplo y marcaron en desuso a varias constantes vmtXXX:
Código Delphi [-]
  ...
  vmtSafeCallException = -32 deprecated;  // don't use these constants.
  vmtAfterConstruction = -28 deprecated;  // use VMTOFFSET in asm code instead
  vmtBeforeDestruction = -24 deprecated;
  vmtDispatch          = -20 deprecated;
  vmtDefaultHandler    = -16 deprecated;
  vmtNewInstance       = -12 deprecated;
  vmtFreeInstance      = -8 deprecated;
  vmtDestroy           = -4 deprecated;

  vmtQueryInterface    = 0 deprecated;
  vmtAddRef            = 4 deprecated;
  vmtRelease           = 8 deprecated;
  vmtCreateObject      = 12 deprecated;

Cita:

Empezado por tema "Assembly directives" de la ayuda
VMTOFFSET retrieves the offset in bytes of the virtual method pointer table entry of the virtual method argument from the beginning of the virtual method table (VMT). This directive needs a fully specified class name with a method name as a parameter (for example, TExample.VirtualMethod), or an interface name and an interface method name.

Mientras emplees VMTOffset y este operador exista, no habrá problema alguno. Pero para versiones antiguas que no tuvieran el operador (no tengo el dato de desde qué versión fue introducido), habría que usar un código algo distinto.

Sin embargo la consulta en la VMT sólo resulta necesaria cuando el método base es abstracto (podría no serlo, implementándolo con sólo Begin y End). Como habrás visto, la otra función que escribí, RedefineProc1, "no" consulta a la VMT (en realidad sí lo hace, como siempre que hacemos referencia o llamamos a un método virtual, pero en este caso es responsabilidad implícita del compilador).

Incluso se me ocurre una tercera forma de hacer la comparación de punteros, que sirva con métodos abstractos y que no use el operador VMTOffset ni ninguna otra referencia explícita a la VMT. No es muy elegante, pero considero que podría ser práctica: consiste en crear una instancia "dummy" de la clase base que declara el método abstracto, para poder hacer una comparación tipo Metodo.Code <> MetodoInstanciaDummy.Code (adaptando la función RedefineProc1 que escribí antes).

Gracias por anexar el código, gushynet. Le echaré un vistazo en estos días.

Saludos.

Al González. :)

gushynet 12-02-2009 06:09:57

Una pregunta mas. Situacion : tengo varios amigos que no programan en delphi sino en c++, VB, C#,....

Cual es la manera de compartir la jerarquia de clases que estoy implementando de forma que mis amigos pudieran declarar objetos de tipo TUniverso en sus programas? podría encapsularse en una dll y que ellos usaran la dll?

En el caso de que si pudiera compartir mi clase mis amigos podrían crearse clases descendientes de TUniverso? (creo que esto es imposible).

Saludos.

Al González 05-03-2009 08:05:27

¡Hola!

Saliéndome un poco del tema y sobre esto que comenté anteriormente:
Cita:

Empezado por Al González (Mensaje 337210)
El problema con MethodAddress es que sólo funciona con métodos publicados.

Recientemente encontré que, bajo cierta directiva de compilación, MethodAddress puede utilizarse con métodos públicos también:
http://www.clubdelphi.com/foros/showthread.php?t=63840

gushynet 06-03-2009 18:59:04

Gracias por seguir pensando en el tema ;)

Como alternativa al método que se ha propuesto he optado por captar la excepcion EAbstractError. Lo que no se es que solucion es mas eficiente:

usar MethodAddress o detectar que el objeto no tiene implementado el metodo a traves de la excepcion EAbstractError.

Lo que no se es si usando la excepcion me dejo algun caso por el camino, por ejemplo, que en la clase padre el metodo sea virtual y en la clase hija no se implementa porque usa el metodo virtual del padre.


PD: el rendimiento de la aplicacion puede verse diezmado si se abusa del control de las excepciones?

Saludos

Al González 06-03-2009 20:52:57

¡Hola!

Cita:

Empezado por gushynet (Mensaje 340438)
Como alternativa al método que se ha propuesto he optado por captar la excepcion EAbstractError. Lo que no se es que solucion es mas eficiente:

usar MethodAddress o detectar que el objeto no tiene implementado el metodo a traves de la excepcion EAbstractError.

MethodAddress no te servirá pues devuelve una dirección única por cada método registrado, sea abstracto o no (http://www.clubdelphi.com/foros/show...94&postcount=3). Sin hablar ya del aumento de tamaño del ejecutable en caso de usar la directiva $MethodInfo.

Atrapar la excepción es una forma de lograrlo, pero tiene varios inconvenientes:

1. Te ves obligado a llamar al método. Es decir, sólo intentando la llamada podrás saber si el método es abstracto o no. Por lo que se reduce la capacidad de maniobra.
2. Dependiendo de las rutinas que el método llame directa o indirectamente, la excepción no será del todo segura para saber si el método es abstracto (el método puede no serlo, pero ¿qué tal si internamente llama a uno que sí?).
3. Puede verse afectado el rendimiento de la aplicación, dependiendo de qué tan frecuentemente se realicen llamadas a los métodos abstractos que se quiere controlar.

En mi opinión, son más eficientes las dos primeras soluciones de las tres que propuse anteriormente. E incluso la tercera (la de la instancia dummy) podría en algunos casos resultar mejor que el manejo de la excepción.


Cita:

Empezado por gushynet (Mensaje 340438)
Lo que no se es si usando la excepcion me dejo algun caso por el camino, por ejemplo, que en la clase padre el metodo sea virtual y en la clase hija no se implementa porque usa el metodo virtual del padre.

Un método deja de ser abstracto para la clase que lo redefine y también para todas las descendientes de ésta. Sin importar que alguna de esas clases descendientes no lo redefina también.

¡Hasta luego!

Al González. :)


La franja horaria es GMT +2. Ahora son las 19:58:15.

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