Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Cómo saber si una classe deriva de otra classe abstracta? (https://www.clubdelphi.com/foros/showthread.php?t=63116)

poyo 29-01-2009 22:20:30

Cómo saber si una classe deriva de otra classe abstracta?
 
Estoy en Delphi 2009, y se habrán enterado o no, le han agregado lo siguiente

type
TMyClass = class abstract (TObject)
...
end;

El modificador "abstract" sirve para que dicha classe no pueda ser instanciada, sólo podrá ser instanciada una classe que derive de ella.

Mi pregunta es la siguiente:

RTTI mediante, hay alguna manera de saber si alguna classe tiene de ancestro alguna classe abstracta?

se entiende la pregunta?
Bueno... la dejo pincando y me voy que tengo que salircorriendo.

saludos

droguerman 30-01-2009 02:02:21

Creo que era:
Código Delphi [-]
if instancia is TClaseAbstracta then ...;

o tambien
Código Delphi [-]
if instancia.inheritsFrom(TClaseAbstracta) then ...;

Delphius 30-01-2009 03:12:48

En tu código asumes que se conoce el nombre de una clase abstracta, y lo que haces es ver si se hereda o no de ésta.

Creo que a lo que apunta poyo es que se desconoce si existe alguna clase abstracta en la rama. Se busca saber, en caso de que exista, cual/es es/son la/s clase/s abstracta/s.

¿Me explico?

Saludos,

Al González 30-01-2009 10:07:58

¡Hola!

No tengo Delphi 2009 en este momento, pero probablemente agregaron algo al respecto en la unidad TypInfo, quizá un campo más en la estructura TTypeData (sólo estoy tratando de adivinar a falta de no poder ver esa unidad :p). ¿Por ahí va la cosa? :)

Me surgió la duda de cómo en versiones anteriores podría averiguarse algo similar: la cuestión de si una clase desciende de otra que tenga uno o más métodos virtuales abstractos.

Para esto pueden examinarse los desplazamientos positivos de la VMT en las clases ancestro, en los cuales el compilador guarda la dirección de memoria de la función _AbstractError (que sencilla solución de parte de Borland) cuando el método es abstracto. Pero el problema es que se necesitaría saber cuántos métodos virtuales tiene declarados cada clase para que la revisión de esos desplazamientos fuese del todo segura (de otra forma, no parece fácil averiguar dónde termina la lista de métodos virtuales, es decir, de qué tamaño es la VMT :confused:).

Divagué un poco con lo anterior, pero fue interesante descubrir con ello que en Delphi 7 no hay validación en tiempo de ejecución de si un método es abstracto o no cuando está a punto de ser llamado, sino que la misma llamada es un salto directo a la función _AbstractError de System.pas. Es decir, ¡_AbstractError es la implementación real de todos los métodos abstractos! :eek:

Estos de Borland eran los puros amos. :cool:

Un _abrazo.

Al González. :)

poyo 30-01-2009 14:18:01

Bueno, primero quería decir que gracias por las respuestas.
Segundo que, lo que quiero hacer, responde a generar automáticamente una especie de árbol de categorías de objetos que tengo creados en base a sus clases abstractas... todas dedivan de una clase madre pero el tema es que se desconozcen la demás ya que la idea es expandir el sistema mediante plugins.

Comento lo que estuve viendo.

Es raro todo esto... pareciera como que lo de las clases abstractas está implementado a medias o no está del todo claro.
En la documentación dice:

"An abstract class is a class with at least one pure virtual function. A virtual function is specified as pure by setting it equal to zero. An abstract class can be used only as a base class for other classes. No objects of an abstract class can be created. An abstract class cannot be used as an argument type or as a function return type. However, you can declare pointers to an abstract class. References to an abstract class are allowed, provided that a temporary object is not needed in the initialization."


hice la siguiente prueba:

declaré:
Código Delphi [-]
procedure TMyClass.showa;
begin
  showmessage(IntToStr(a));
end;

function TMyClass.retself: TMyClass;
begin
  result := self;
end;

procedure TMyClass.ArgOfAbstractClass(AClass: TMyClass);
begin
  //do nothing
end;

implementation

procedure TMyClass.showa;
begin
  showmessage(IntToStr(a));
end;

////////////////////

procedure prueba;
var
  a : TMyClass;
begin
  a := TMyClass.Create;
  a.a := 10;
  a.showa;
  showmessage(a.retself.ClassName);
end;

Y lo ejecuté y funcionó como si nada... el compilador no me tiró ni un warning y en runtime tampoco se me avisó de nada.

revisé los units Typinfo, system y classes y no vi nada que haga referencia.
A lo mejor no revisé bien... aunque por la manera de funcionar, o no estoy entendiendo del todo el concepto o está medio verde la implementación.

parece que TMyClass = class abstract funciona como si fuera un simple comentario
TMyClass = class // abstract

de hecho si se declara de la siguiente manera compila igual:
TMyClass = class abstract abstract abstract abstract abstract abstract abstract abstract
curioso, no? :confused:

Ya me arreglé (provisoriamente) poniéndo una función virtual llamada "isBaseClass".

Al González 30-01-2009 17:03:06

Que interesante lo que comentas, Poyo. Pareciera que esa palabra reservada es solamente informativa cuando se utiliza en la cabecera declarativa de la clase.

¿Pero qué pasa si añades a esa clase un método "Virtual; Abstract;"? ¿También así te deja crear la instancia?

Es posible que la inclusión de esta nueva directiva en Delphi 2009 Win32 haya sido por mera compatibilidad con la sintaxis de Delphi .NET.

Por otra parte, si el compilador genera código máquina de manera semejante que en Delphi 7, la solución podría estar en algo similar a lo que comenté en el mensaje anterior (¿pero cómo saber cuántas entradas tiene una VMT?)

Saludos.

Al González. :)

poyo 31-01-2009 00:09:22

Al, si añado un método "Virtual; Abstract;" deja compilar y crear la instancia...
arroja un warning igual que siempre:
...Constructing instance of 'TMyClass2' containing abstract method ...

Si no me equivoco, esta característica está en el delphi desde hace algunos años aunque nunca lo probé en versiones anteriores y ahora no tengo ninguna. :(

http://dn.codegear.com/article/34324

con respecto a saber cuántos métodos virtuales hay en la VMT, abrí otro hilo para que este no se vaya por las ramas ;)


La franja horaria es GMT +2. Ahora son las 01:15: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