Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi überkreuzender Bezug von Units .. kleiner Workaround (https://www.delphipraxis.net/100197-ueberkreuzender-bezug-von-units-kleiner-workaround.html)

stoxx 24. Sep 2007 13:39


überkreuzender Bezug von Units .. kleiner Workaround
 
Habe eine recht schöne Lösung gefunden, wie man trotz nicht gestattetem überkreuzenden Bezug von zwei Units, diese Geschichte schön umgehen kann, ohne ständig Casts durchzuführen ...

Ziel. Zwei klassen brauchen im Klassenmodell eine gegenseitige Referenz aufeinander, befinden sich aber in verschiedenen Units.. in anderen Sprachen ja nicht so das Problem, in delpi aber nicht möglich.....


Delphi-Quellcode:
TClassA = class(TObject)
  linkClassB : TClassB;
end;


TClassB = class(TObject)
  linkClassA : TClassA;
end;


Lösung ...


Delphi-Quellcode:
TClassA = class(TObject)
  linkClassB : TClassB;
end;


TClassB = class(TObject)
  _linkClassA : TObject;
end;
man speichert in _linkClassA die Referenz ab ... und greift nur noch über properties einer ClassHelper Klasse auf diese Referenz zu..

diese befindet sich aber NUR im Implementationteil der Unit, damit ist ein quasi überkreuzender Bezug von Units möglich..


Delphi-Quellcode:
implementation

uses UnitClassA;

type
  TConvertHelper = class helper for TClassB
  private
    function Get_linkClassA: TClassA;
    procedure Set_LinkClassA(const Value: TClassA);
  published

    property LinkClassA : TClassA read Get_LinkClassA write Set_LinkClassA;
  end;


//==============================================================================


function TConvertHelper.Get_LinkClassA: TClassA;
begin
  result := TClassA(_linkClassA);
end;
//==============================================================================
procedure TConvertHelper.Set_LinkClassA(const Value: TClassA);
begin
  _linkClassA := Value;
end;

und jetzt kann man in irgendeiner Methode von TClassB wunderschön mit


Delphi-Quellcode:
self.linkClassA
auf das Object zugreifen, ohne ständig rumcasten zu müssen :-)

Dezipaitor 25. Sep 2007 13:51

Re: überkreuzender Bezug von Units .. kleiner Workaround
 
Ok und in welcher Delphiversion funktioniert das?

hoika 25. Sep 2007 14:05

Re: überkreuzender Bezug von Units .. kleiner Workaround
 
Hallo

http://delphi.about.com/od/delphifor...asshelpers.htm


also Delphi.Net: D2005/2006 (?) aufwärts.


Heiko

Dezipaitor 25. Sep 2007 14:40

Re: überkreuzender Bezug von Units .. kleiner Workaround
 
Also in kleineren Versionen, überprüfe ich mit "is" bei "write property" ob es die korrekte Klasse ist.

Delphi-Quellcode:
property Xy : TObject read GetXy write SetXy;

procedure ...SetXy(Xy : TObject);
begin
  if not (Xy is TMyClass) then
    raise ....
end;
Ich weiß jedoch nicht, ob es auch für abgeleitete Klassen funktioniert. Ich könnte mir es aber vorstellen.

stoxx 26. Sep 2007 00:19

Re: überkreuzender Bezug von Units .. kleiner Workaround
 
also sowohl in .NET als auch unter Win32 funktioniert das.
Ab Delphi 2005

Hansa 26. Sep 2007 00:31

Re: überkreuzender Bezug von Units .. kleiner Workaround
 
Zitat:

Zitat von stoxx
..Ziel. Zwei klassen brauchen im Klassenmodell eine gegenseitige Referenz aufeinander, befinden sich aber in verschiedenen Units..

Dann ist das Klassenmodell in 90 % der Fälle falsch. Lerne besser programmieren und spiele nicht so viel Billard. :mrgreen:

Zitat:

in anderen Sprachen ja nicht so das Problem, in delpi aber nicht möglich.....
Unser Ober-Schwuchtel würde dazu sagen : Und das ist auch gut so. :mrgreen:

Im Ernst : glaube nicht, dass ich solch ein Konstrukt in zig-Programmen verwenden MUSS. Es gibt keins. 8)

mkinzler 26. Sep 2007 05:38

Re: überkreuzender Bezug von Units .. kleiner Workaround
 
Zitat:

Im Ernst : glaube nicht, dass ich solch ein Konstrukt in zig-Programmen verwenden MUSS. Es gibt keins. Cool
Unter Win32 vielleicht nicht, aber unter .Net ist dies ein weitverbreitetes Konzept, vorallem bei den neueren Techniken

alzaimar 26. Sep 2007 06:50

Re: überkreuzender Bezug von Units .. kleiner Workaround
 
Zitat:

Zitat von Hansa
Unser Ober-Schwuchtel würde dazu sagen : ... :mrgreen:

Ihr Saarländer müsst grad reden, ihr mit Eurem narzißtischen Hobbit. :mrgreen:

Äh?
Delphi-Quellcode:
Type
  TClassA = Class;
  TClassB = Class;
 ...
  TClassA = Class
    fRefB : TClassB;
  End;
  TClassB = Class
    fRefA : TClassA;
  End;
Oder hab ich was verpasst? :gruebel:

uligerhardt 26. Sep 2007 08:07

Re: überkreuzender Bezug von Units .. kleiner Workaround
 
Zitat:

Zitat von alzaimar
Oder hab ich was verpasst? :gruebel:

Ja:
Zitat:

Zitat von stoxx
Ziel. Zwei klassen brauchen im Klassenmodell eine gegenseitige Referenz aufeinander, befinden sich aber in verschiedenen Units..

Hatte aber beim ersten Lesen den gleichen Gedanken. Zum Glück konnte ich meinen Reflex zu posten noch rechtzeitig unterdrücken. :)

Uli.

alzaimar 26. Sep 2007 08:13

Re: überkreuzender Bezug von Units .. kleiner Workaround
 
Ah. Na dann ... Ist die Aufteilung in Units falsch. Beide Klassen gehören, da untrennbar miteinander verbunden, auch zusammen.

uligerhardt 26. Sep 2007 08:17

Re: überkreuzender Bezug von Units .. kleiner Workaround
 
Zitat:

Zitat von alzaimar
Ah. Na dann ... Ist die Aufteilung in Units falsch. Beide Klassen gehören, da untrennbar miteinander verbunden, auch zusammen.

Ist nicht immer machbar. Ich hab z.B. eine Form, auf der zur Laufzeit unterschiedliche Kind-Frames plaziert werden. Parentform und aktueller Frame müssen sehr viel voneinander wissen, aber, da visuell designt, in unterschiedlichen Units sein.

SirThornberry 26. Sep 2007 08:27

Re: überkreuzender Bezug von Units .. kleiner Workaround
 
Zitat:

Zitat von uligerhardt
Zitat:

Zitat von alzaimar
Ah. Na dann ... Ist die Aufteilung in Units falsch. Beide Klassen gehören, da untrennbar miteinander verbunden, auch zusammen.

Ist nicht immer machbar. Ich hab z.B. eine Form, auf der zur Laufzeit unterschiedliche Kind-Frames plaziert werden. Parentform und aktueller Frame müssen sehr viel voneinander wissen, aber, da visuell designt, in unterschiedlichen Units sein.

Das klingt mir nach falschem Design. Das klingt danach als ob Oberfläche und Funktionalität vermixt wurden. Ansonsten bildet man die ganze Funktionalität in nicht visuellen Objekten ab und per Events kann man die Oberfläche über Änderungen Informieren. Umgekehrt kann bei Eingabe über die Gui eine Methode der nicht visuellen Objekte aufgerufen werden.

alzaimar 26. Sep 2007 08:35

Re: überkreuzender Bezug von Units .. kleiner Workaround
 
Dann löse dieses Dilemma mit Events. So ein Frame muss doch nicht wissen, das es auf einer TFoobarForm ist. Wozu dann ein Frame? Der Sinn eines Frames ist doch, das man es wieder verwenden kann. Aber so sind die beiden Klassen wirklich untrennbar verbunden.

Es ist doch bestimmt so, das dein Hauptformular irgendetwas machen muss, wenn sich im Frame Daten ändern. Und Du veränderst die Daten der Hauptform im Code/Kontext des Frames.

Es ist praktischer, wenn das Frame seinem Eigentümer (oder wer auch immer das wissen will), Bescheid gibt, wenn sich etwas ändert. Dann kann der Eigentümer angemessen darauf reagieren, das Frame muss gar nichts über ihn wissen und alle (vor allen Dingen die OOP-Gemeinde) sind zufrieden.

Du kannst das dann sehr leicht mit Events lösen:
Spendiere dem Frame ein Event 'OnDataChanged' mit einem Parameter, der besagt, WAS geändert wurde, etwa so:

Delphi-Quellcode:
Type
  TDataOnFrameChangedEvent = Procedure (Sender : TObject; aControl : TControl);
Und dann weist Du jedem OnChange-Event deiner Eingabefelder auf dem Frame diese Methode zu:
Delphi-Quellcode:
Procedure TMyFrame.DataOnFrameChanged (Sender : TObject);
Begin
  If Assigned (fDataOnFrameChanged) And (Sender Is TControl) Then
    fDataOnFrameChangedEvent (Self, TControl (Sender));
End;
In Deinem Hauptformular erzeugst Du dir so eine Methode, implementierst *dort* die vorzunehmenden Aktionen und weist im FormCreate dem Frame-Ereignis diese Methode zu:
Delphi-Quellcode:
Procedure TMyMainForm.ReactOnDataChanged (Sender : TObject; aControl : TControl);
Begin
  If Sender = frmMyFrame Then
    If aControl = frmMyFrame.edVorname Then
      ShowMEssage(Format ('Der Vorname wurde in %s geändert',[TEdit (aControl).Text]));
End;

Procedure TMyMainForm.FormCreate (Sender : TObject);
Begin
  ...
  frmMyFrame.OnDataOnFrameChangted := ReactOnDataChanged
End;
Wenn sich im Frame nun etwas ändert, wird immer die Methode 'ReactOnDataChanged' über den Event-Mechanismus aufgerufen.

Ich finde diese Lösung auch deswegen besser, weil alle Aktionen, die Du im Hauptformulat in Abhängigkeit des Frames ausführst, in der Methode 'ReactOnDataChanged' konzentriert und an einer Stelle implementiert sind. Das ist übersichtlich und einfacher wartbar.

uligerhardt 26. Sep 2007 08:41

Re: überkreuzender Bezug von Units .. kleiner Workaround
 
Zitat:

Zitat von SirThornberry
Das klingt mir nach falschem Design. Das klingt danach als ob Oberfläche und Funktionalität vermixt wurden. Ansonsten bildet man die ganze Funktionalität in nicht visuellen Objekten ab und per Events kann man die Oberfläche über Änderungen Informieren. Umgekehrt kann bei Eingabe über die Gui eine Methode der nicht visuellen Objekte aufgerufen werden.

Es geht durchaus um echte GUI-Funktionalität, die zwischen Form und Frame koordiniert werden muss - Toolbars "mergen", Größenanpassungen usw.usf. Hab oft und lange überlegt, wie ich das besser trennen könnte, bin aber nie auf die "perfekte" Lösung gekommen. :)
FTR: Meine Frames implementieren mittlerweile ein Interface, über das die Form ihre Funktionalität aufruft. Das Interface ist aber zu "ad hoc" für meinen Geschmack aufgebaut - riecht ziemlich nach Workaround. Andererseits: es funktioniert. :)

uligerhardt 26. Sep 2007 08:49

Re: überkreuzender Bezug von Units .. kleiner Workaround
 
Zitat:

Zitat von alzaimar
Dann löse dieses Dilemma mit Events. So ein Frame muss doch nicht wissen, das es auf einer TFoobarForm ist. Wozu dann ein Frame? Der Sinn eines Frames ist doch, das man es wieder verwenden kann. Aber so sind die beiden Klassen wirklich untrennbar verbunden.

Frames deshalb, weil ich einen komplexen Teil eines noch komplexeren Formulars zur Laufzeit austauschen will. Ohne genau diese eine Form als Rahmen haben die Frames wenig Sinn.

Aber ich werde mir deine Überlegungen mal genauer zu Gemüte führen, wenn mal etwas mehr Zeit ist. Vielleicht finde ich wirklich noch ein paar bessere "Sollbruchstellen" zwischen Form und Frame.

Und vielen Dank für deine Ideen!

Uli.

stoxx 26. Sep 2007 11:16

Re: überkreuzender Bezug von Units .. kleiner Workaround
 
Zitat:

Dann ist das Klassenmodell in 90 % der Fälle falsch.
Hallo Hansa,

da stimme ich Dir zu. Aber es bleiben eben 10 Prozent übrig :)
Und für diese 10 Prozent soll es ja auch eine Lösung geben.
Auch ich bin der Meinung dass ein hirarchiches Klassenmodell besser ist.

Eine Klasse kann eine andere Klasse als Eigentümer haben und zurück gehts per Events. Sehr richtig.

Und ich muss Dir auch Recht geben, dass solche eng verknüpften Klassen dann auch in eine Unit gehören.
Ich arbeite aber effektiver, wenn ich micht nicht durch ellenlange Units durcharbeiten muss. Auf zwei kleinere Units verteilt ist das für mich übersichtlicher. Aber das ist eine perönliche Meinung.

Wenn Du magst, können wir ja gern mal über mein Klassenmodell diskutieren, ich bin sehr lernbereit!
Aber ob Hochwürden auch so gnädig ist?

Und was hast Du gegen Billiard? verlierst wohl immer? *g*

beste Grüße

Elvis 26. Sep 2007 11:36

Re: überkreuzender Bezug von Units .. kleiner Workaround
 
Zitat:

Zitat von stoxx
Wenn Du magst, können wir ja gern mal über mein Klassenmodell diskutieren, ich bin sehr lernbereit!
Aber ob Hochwürden auch so gnädig ist?

Hansas Verständnis für OO fängt beim Objectrepository der IDE für Forms an und es hört 1cm danach auf. Es ist also effektiv nicht existent.
Er hat bis heute nicht kapiert warum es abstrakte Methoden gibt, du kannst ihn also in fachlichen Dingen komplett ignorieren.
Manchmal wünschte ich, er könnte kurzzeitig verstehen worum es geht, so dass er sich grün & blau ärgern kann. (Über den Unsinn, den er so schreibt...)

Hansa 26. Sep 2007 11:53

Re: überkreuzender Bezug von Units .. kleiner Workaround
 
@Elvis : wo bleiben denn deine theoretischen Theorien, die die Welt nicht braucht ? :lol: Ich meine die völlig abstrakten, die keiner benutzt und du keinen Widerspruch zu befürchten hast ? Echt lächerlich abstrakt. :mrgreen:

Stoxx, schildere mal das konkrete Problem. "Überkreuz" das riecht schon ziemlich nach Spaghetti-Code.

uligerhardt 26. Sep 2007 11:56

Re: überkreuzender Bezug von Units .. kleiner Workaround
 
Zitat:

Zitat von Elvis
Er hat bis heute nicht kapiert warum es abstrakte Methoden gibt, du kannst ihn also in fachlichen Dingen komplett ignorieren.
Manchmal wünschte ich, er könnte kurzzeitig verstehen worum es geht, so dass er sich grün & blau ärgern kann. (Über den Unsinn, den er so schreibt...)

Hansa, Elvis, meint ihr, es lohnt sich, schon mal Popcornf zu holen? :)

stoxx 26. Sep 2007 12:20

Re: überkreuzender Bezug von Units .. kleiner Workaround
 
Zitat:

"Überkreuz" das riecht schon ziemlich nach Spaghetti-Code.
na gut, vielleicht hätte ich drunter schreiben sollen. Liebe Kinder vor dem Fernseher, bitte nicht nachmachen!

Zitat:

Stoxx, schildere mal das konkrete Problem.
vielleicht mal beim Billiard :lol:


ich möchte mich aber jetzt nicht weiter in Eure Familienangelegenheiten einmischen, da tun sich ja Abgründe auf. Aber eigentlich magt ihr Euch doch, trinkt doch mal ein Bier zusammen.

Aber gerade abstracte Methoden nehmen Dir doch die Schreibarbeit von case Anweisungen ab.
Und genau das ist doch der Knackpunkt. Bei Quelltexterweiterungen an so wenigen Stellen wie möglich im Quelltext was ändern zu müssen.
(Quelltextsicherheit) -> abstrakte Methoden ...

Und ich verwende abstrakte Methoden auch durchaus.

mkinzler 26. Sep 2007 12:40

Re: überkreuzender Bezug von Units .. kleiner Workaround
 
Abstraktion ist auch ein Grundprinzip der OOP

Dezipaitor 26. Sep 2007 18:07

Re: überkreuzender Bezug von Units .. kleiner Workaround
 
ICh habe auch so ein "überkreuzender Bezug"-Problem:

Delphi-Quellcode:
unit Descriptor;
uses Token,...;

TSecurityDescriptor = Class(TObject)
...
{@Name combines a parent and a creator security descriptor into a new security descriptor.
For detailed information see MSDN [url]http://msdn2.microsoft.com/en-us/library/aa446581.aspx[/url]

@param(ObjectType A Pointer to a GUID that defines the type. Set to nil if it does not exist.)
@param(GenericMap Defines the generic map class which maps generic access rights to specific access rights.)
@param(Token defines the token instance which is used to check for access. Can be nil to use
process or thread token.)
}
constructor CreatePrivateObjectSecurity(
      const ParentSecurityDescriptor: TJwSecurityDescriptor;
      const CreatorSecurityDescriptor: TJwSecurityDescriptor;
      const ObjectType : PGUID;
      const IsDirectoryObject : Boolean;
      const AutoInheritFlags : Cardinal;
      const GenericMap : TJwSecurityGenericMappingClass;
      const Token : TSecurityToken = nil); //Fehler
...

end.

unit ...Token;
uses Descriptor,...;

TSecurityToken = Class(TObject)
...
{Sicherheitsdeskriptor für das Token}
property SecurityDescriptor : TSecurityDescriptor read GetSecurityDescriptor write SetSecurityDescriptor;
...
Im Moment verwende ich folgende Deklaration:
Delphi-Quellcode:
constructor CreatePrivateObjectSecurity(
      const ParentSecurityDescriptor: TJwSecurityDescriptor;
      const CreatorSecurityDescriptor: TJwSecurityDescriptor;
      const ObjectType : PGUID;
      const IsDirectoryObject : Boolean;
      const AutoInheritFlags : Cardinal;
      const GenericMap : TJwSecurityGenericMappingClass;
      const Token : TObject = nil); //Ok
Dabei wird Token auf den Typ überprüft :

Delphi-Quellcode:
if not (Token is TSecurityToken) then
  raise
Was könnte man da Vernünftiges machen?

stoxx 26. Sep 2007 18:39

Re: überkreuzender Bezug von Units .. kleiner Workaround
 
Zitat:

Was könnte man da Vernünftiges machen?
erstmal überprüfen, ob nicht ein Event ausreicht und ob Du wirklich eine Referenz von einem Object auf das andere Object benötigst.
Ein TButton kommuniziert ja auch nur über Events wie OnClick zum Formular zurück und nicht mit dem direkten Aufruf eines Formulars, auf dem es sich befindet..... Und deswegen lässt er sich ja so universell verwenden :-)
Deine Tokenklasse ist wahrscheinlich auch universell?

Ansonsten, das Prinzip mit der ClassHelper Lösung nicht verstanden? .. hmmm

Dezipaitor 26. Sep 2007 18:56

Re: überkreuzender Bezug von Units .. kleiner Workaround
 
Zitat:

Zitat von stoxx
Zitat:

Was könnte man da Vernünftiges machen?
erstmal überprüfen, ob nicht ein Event ausreicht und ob Du wirklich eine Referenz von einem Object auf das andere Object benötigst.
Ein TButton kommuniziert ja auch nur über Events wie OnClick zum Formular zurück und nicht mit dem direkten Aufruf eines Formulars, auf dem es sich befindet..... Und deswegen lässt er sich ja so universell verwenden :-)
Deine Tokenklasse ist wahrscheinlich auch universell?

Ansonsten, das Prinzip mit der ClassHelper Lösung nicht verstanden? .. hmmm

Das muss alles noch mit Delphi5 funktionieren. Sry. Habe ich vergessen zu erwähnen.
Und wie soll denn hier ein Event funktionieren?


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:45 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