Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Neuen Beitrag zur Code-Library hinzufügen (https://www.delphipraxis.net/33-neuen-beitrag-zur-code-library-hinzufuegen/)
-   -   Delphi Klasse eines Objekts zur Laufzeit ändern (https://www.delphipraxis.net/117110-klasse-eines-objekts-zur-laufzeit-aendern.html)

shmia 11. Jul 2008 16:54


Klasse eines Objekts zur Laufzeit ändern
 
Mit folgender Prozedure ist es möglich, die Klasse eines Objekts zur Laufzeit zu ändern.
Wichtig dabei ist, dass die neue Klasse immer ein direkter Nachkomme der Klasse des Objekts ist.

Ausserdem kann man in der neuen Klasse nur virtuelle Methoden überschreiben und keine neuen Felder hinzufügen.
Sollte die neue Klasse grösser sein als die alte, wird eine Exception erzeugt.
Mit Felder sind hier die lokalen Variablen der Klasse (meist unter Abschnitt private) gemeint.
Da das Objekt schon existieren muss, sind Eingriffe in den Konstruktor nicht möglich.

Delphi-Quellcode:
procedure ChangeClass(obj : TObject; NewClass:TClass);
type PClass = ^TClass;
begin
  if Assigned(obj) and (obj.ClassType <> NewClass) then
  begin
    if obj.ClassType <> NewClass.ClassParent then
       raise Exception.CreateFmt('can''t change Object of class %s to class %s', [obj.ClassName, NewClass.ClassName]);
    if obj.InstanceSize <> NewClass.InstanceSize then
       raise Exception.CreateFmt('Class %s - invalid instance size', [NewClass.ClassName]);
    PClass(obj)^ := NewClass;
  end;
end;
Hier noch ein kleines Anwendungsbeispiel.
Delphi-Quellcode:
// Es wird die Klasse eines Objekts von TButton nach TBeepButton geändert.
type
TBeepButton = class(TButton)
protected
  procedure Click;override;
end;

procedure TBeepButton.Click;
begin
  Beep;
  inherited;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
   ChangeClass(Button1, TBeepButton);
end;
Siehe auch Tutorial: Ändern der Klassenhierarchie

Luckie 11. Jul 2008 22:01

Re: Klasse eines Objekts zur Laufzeit ändern
 
Gibt es dafür auch einen praktischen Anwendungsfall? Oder anders gesagt, wann braucht man so was? So unbedarft auf den ersten Blick kommt mir das ziemlich unsauber vor, wenn man so etwas brauchen würde.

GuenterS 11. Jul 2008 22:39

Re: Klasse eines Objekts zur Laufzeit ändern
 
Könnte man dann brauchen, wenn man nur Zugriff auf eine Instanz eines Formulares hat und dort vielleicht einen Button austauschen möchte man dies aber leider nicht per Quellcode machen kann, da man nur die dcu Datei hat.

Apollonius 12. Jul 2008 10:08

Re: Klasse eines Objekts zur Laufzeit ändern
 
Hallvard Vassbotn hat diesen Hack einmal vorgestellt, als es darum ging, das Flackern von TProgressBars unter Vista abzustellen.

shmia 14. Jul 2008 10:18

Re: Klasse eines Objekts zur Laufzeit ändern
 
Zitat:

Zitat von Luckie
Gibt es dafür auch einen praktischen Anwendungsfall?

Wenn z.B. eine grössere Datenbankanwendung plötzlich mit FoxPro Tabellen arbeiten soll ergibt sich das Problem, dass alle Felder anhängende Leerzeichen haben.
Man könnte bei jedem Zugriff auf ein String-Feld ein TrimRight hinzufügen.
Das ist natürlich sehr aufwendig und manchmal gar nicht möglich.
Man könnte eine Klasse TTrimedStringField von der Klasse TStringField ableiten.
Wenn man dann im Event [TDataSet.]AfterOpen alle TStringField Klassen in TTrimedStringField ändert, kann man das Problem mit wenig Aufwand in der Griff bekommen.

Auch bei Anwendung des State Design-Patterns ist das Ändern der Klasse hilfreich.


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:16 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz