Ver Mensaje Individual
  #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
Reputación: 30
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