AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Trick um "überkreuzenden Bezug" von Units zu umgehen ?
Thema durchsuchen
Ansicht
Themen-Optionen

Trick um "überkreuzenden Bezug" von Units zu umgehen ?

Offene Frage von "dartrax"
Ein Thema von stoxx · begonnen am 5. Okt 2004 · letzter Beitrag vom 8. Mai 2005
Antwort Antwort
Seite 3 von 3     123   
dartrax

Registriert seit: 10. Nov 2004
26 Beiträge
 
#21

Re: Trick um "überkreuzenden Bezug" von Units zu u

  Alt 5. Mai 2005, 16:18
Hallo!

Ich habe es jetzt mit der Idee mit den Interfaces von rantaplan gemach. Ohne, dass ich eine "Unit3" benötige.

Trotzdem würde mich interessieren, wie dizzys Lösung dieses Problem umschifft; ich habe das folgende Beispiel doch genau so gemacht, wie es gedacht ist mit der zusätzlichen Unit, oder?

Delphi-Quellcode:
unit Unit1;

interface

uses Unit3;

implementation

procedure TClass1.DoOneThing(Class2: TClass2);
begin
  // I'm really busy
end;

end.
Delphi-Quellcode:
unit Unit2;

interface

uses Unit3;

implementation

procedure TClass2.DoAnotherThing(Class1: TClass1);
begin
  // That's too much for me
end;

end.
Delphi-Quellcode:
unit Unit3;

interface

type
// Forward-deklarationen aller Klassen
TClass1 = class;
TClass2 = class;

// Vollständige Deklaration Class 1
TClass1 = class
private
  // Verweis auf Class 2
  Class2: TClass2;
public
  // Irgendeine Methode
  procedure DoOneThing(Class2: TClass2);
end;

// Vollständige Deklaration Class 2
TClass2 = class
private
  // Verweis auf Class 1
  Class1: TClass1;
public
  // Irgendeine Methode
  procedure DoAnotherThing(Class1: TClass1);
end;

implementation

end.
Jetzt meckert der Compiler wegen ungenügenden Forward- oder External-Deklarationen in Unit3 - Logisch, die Implementierun findet ja in den ursprünglichen Units statt. Trotzdem wurde das Problem von niemandem hier erwähnt. Wenn ich nun im implementation-Teil von Unit3 ein Uses auf die ursprünglichen Units setze:
Delphi-Quellcode:
implementation

uses Unit1, Unit2;

end.
kommt der Fehler natürlich nicht mehr, jedoch mag der Compiler nun in den ursprünglichen Units die Implementierungen nicht mehr - was ich nicht nachvollziehen kann.

Ob der Kreuzbezug richtig ist oder nicht möchte ich hier nicht zur Diskussion stellen - ich schließe mich da der Meinung von BenBe an.

dartrax
Meine Homepage: www.dartrax.de
  Mit Zitat antworten Zitat
n0b0dy@home

Registriert seit: 1. Jan 2003
7 Beiträge
 
#22

Re: Trick um "überkreuzenden Bezug" von Units zu u

  Alt 5. Mai 2005, 20:13
hier noch eine moeglichkeit mit interface

Delphi-Quellcode:
unit UInterfaces;

interface

type

  IKlasse1 = interface
    function tellName(): string;
    function doSomething(): string;
  end;

  IKlasse2 = interface
    function tellName(): string;
    function doSomething(): string;
  end;

implementation

end.
dann die beiden implementierunsklassen

Klasse 1
Delphi-Quellcode:
unit UKlasse1;

interface

uses ComObj, UInterfaces;

type
  TKlasse1 = class(TComObject, IKlasse1)

  public
    InterfaceZurKlasse2: IKlasse2;

    function tellName(): string;
    function doSomething(): string;

    constructor Create;

  end;

implementation

constructor TKlasse1.Create();
begin

end;

function TKlasse1.tellName(): string;
begin
  Result := 'Bin Klasse1';
end;

function TKlasse1.doSomething(): string;
begin
  Result := 'Bin in Klasse1 und rufe jetzt Klasse2 auf: ';

  if not(InterfaceZurKlasse2 = nil) then
    Result := Result + InterfaceZurKlasse2.tellName()
  else
    Result := Result + 'Ups, nix da!!';
end;

end.
Klasse 2
Delphi-Quellcode:
unit UKlasse2;

interface

uses ComObj, UInterfaces;

type
  TKlasse2 = class(TComObject, IKlasse2)

  public
    InterfaceZurKlasse1: IKlasse1;
    
    function tellName(): string;
    function doSomething(): string;

    constructor Create;

  end;

implementation

constructor TKlasse2.Create();
begin

end;

function TKlasse2.tellName(): string;
begin
  Result := 'Bin Klasse2';
end;

function TKlasse2.doSomething(): string;
begin
  Result := 'Bin in Klasse2 und rufe jetzt Klasse1 auf: ';

  if not(InterfaceZurKlasse1 = nil) then
    Result := Result + InterfaceZurKlasse1.tellName()
  else
    Result := Result + 'Ups, nix da!!';

end;

end.
und die anwendung
Delphi-Quellcode:
unit UMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, UKlasse1, UKlasse2, UInterfaces, StdCtrls;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
  var
    Klasse1: TKlasse1;
    Klasse2: TKlasse2;

    InterfaceKlasse1: IKlasse1;
    InterfaceKlasse2: IKlasse2;
begin


  Klasse1 := TKlasse1.Create();
  Klasse2 := TKlasse2.Create();

  Klasse1.InterfaceZurKlasse2 := Klasse2;
  Klasse2.InterfaceZurKlasse1 := Klasse1;

  Memo1.Clear();

  Memo1.Lines.Add(Klasse1.doSomething());
  Memo1.Lines.Add(Klasse2.doSomething());



end;

end.
so ungefaehr eben ;o)
  Mit Zitat antworten Zitat
Robert_G
(Gast)

n/a Beiträge
 
#23

Re: Trick um "überkreuzenden Bezug" von Units zu u

  Alt 5. Mai 2005, 20:29
Zitat von BenBE:
Einfachste und sauberste Lösung:

Forward-Deklaration von TClass2
Deklaration von TClass1
Deklaration von TClass2

Alles in eine Unit packen.

Anders geht's nicht!
Es geht anders, einfacher und sauberer!
Einfacher ist in dem Moment relativ.
Ich persönlich finde es grob unsauber und unhadlich wenn:
  • mich eine Klasse, zwingt eine andere in der gleichen Unit zu deklarieren
  • ich auch immer diese zweite Klasse überall mitscheleifen muss, wo Klasse1 benutzt wird
  • Interface und Implemetierung im Chaos untergehen

Einfach mal einen Blick in Classes.pas werfen. Dann sieht man sehr schnell wie einfach man sich mit Forward declares beide Hände fesselt und die Units ins grenzenlose wachsen lassen.

Nobodys Weg zeigt absolut in die richtige Richtung.
Zwei Möglichkeiten dazu findet man hier: http://www.delphipraxis.net/internal...=359178#359178

@Nobody, statt TComObject wären TInterfacedObject, TContainerObject oder TAggregatedObject bessere Basisklassen für die Implementierung von Interfaces. (Außerdem werden sie schon in System deklariert )
  Mit Zitat antworten Zitat
n0b0dy@home

Registriert seit: 1. Jan 2003
7 Beiträge
 
#24

Re: Trick um "überkreuzenden Bezug" von Units zu u

  Alt 5. Mai 2005, 21:30
@robert: hab schon lange nicht mehr in delphi entwickelt, deswegen hab ich das erstbeste genommen. hast aber recht )
  Mit Zitat antworten Zitat
Robert_G
(Gast)

n/a Beiträge
 
#25

Re: Trick um "überkreuzenden Bezug" von Units zu u

  Alt 5. Mai 2005, 21:33
Zitat von n0b0dy@home:
@robert: hab schon lange nicht mehr in delphi entwickelt, deswegen hab ich das erstbeste genommen. hast aber recht )
Wie gesagt: Du lagst (, bis auf TComObject, ) absolut richtig.
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#26

Re: Trick um "überkreuzenden Bezug" von Units zu u

  Alt 6. Mai 2005, 10:47
Zitat:
naja, das ganze laesst aber auf einen design-fehler schliessen, wenn ich einen kreuzbezug erzeuge. es wuerde mich schon interessieren, warum er hier von noeten ist.
Sehe ich auch so. Baue die beiden überkreuzenden Klassen in eine 3. Unit ein, aber als abstrakte Basisiklassen. In den anderen 2 Units leitest du nun von diesen beiden Basisklassen die implementierenden Klassen ab. Wenn du das clever anstellst wirst du absolut ohne Typcast und der gleichen auskommen.

Zitat:
Dann wär die VCL ein einziger Designfehler: Dort wird in TControl bereits auf TWinControl verwiesen, und ähnliches.
Nein, dieser Vergleich ist schlicht falsch. Es gibt einen definitiven Designunterschied in der Hierarchie von TWinControl und TControl. Denn ein TControl kann niemals ein Parent eines TWinControls sein, und alleine diese Design-Richtlinie bedingt das sich die fast komplette Schnittstelle in den relevanten Teilen von TControl und TWinControl unterscheiden. Es wäre ohne größeren Aufwand durchaus möglich TControl und TWinControl in separate Units auszulagern. Nur, da es beides im Grunde "abstrakte" Klassen sind mit gleichem Designbezug wäre dies ziemlich kontraproduktiv.

Die VCL enthält meiner Meinung nach fast keine OOP Designschwächen in ihrer Klassenhierarchie.

Gruß hagen
  Mit Zitat antworten Zitat
n0b0dy@home

Registriert seit: 1. Jan 2003
7 Beiträge
 
#27

Re: Trick um "überkreuzenden Bezug" von Units zu u

  Alt 6. Mai 2005, 13:42
Zitat:
Sehe ich auch so. Baue die beiden überkreuzenden Klassen in eine 3. Unit ein, aber als abstrakte Basisiklassen. In den anderen 2 Units leitest du nun von diesen beiden Basisklassen die implementierenden Klassen ab. Wenn du das clever anstellst wirst du absolut ohne Typcast und der gleichen auskommen.
auch eine moeglichkeit. nur bei verteilten anwendungen wird es dann wieder eng. aber wenn die sache in einer anwendung bleibt, ist es sicher die einfacherere loesung (wuerde sie auch bevorzugen).
ja|nein|vielleicht
  Mit Zitat antworten Zitat
Robert_G
(Gast)

n/a Beiträge
 
#28

Re: Trick um "überkreuzenden Bezug" von Units zu u

  Alt 7. Mai 2005, 02:45
Zum ursprünglichen Problem:
Zitat von stoxx:
kennt irgendjemand eine clevere Möglichkeit um nicht Haufen Umwege gehen zu müssen ?
Ich habe zwei Objecte in zwei verschiedenen Units.
Und will von jedem Object einen Zeiger auf das andere Object speichern können.

in Unit1:

Code:
TClass1 = class

 p : TClass2;

end;
in Unit2:

Code:
TClass2 = class

 p : TClass1;

end;
dummerweise muss ich nun in Unit2 die Unit1 in den Uses Klauseln einfügen und umgekehrt.
Dummerweise kommt ja nun die Meldung "Überkreuzender Bezug zweier Units"
HAb schon einige ZEit gegrübelt, kann man das irgendwie über eine dritte Unit umgehen ?
Die effektivste Umgehung des Problems dürfte es wohl sein, das Problem GANZ aus der Welt zu schaffen.
Nachdem ich heute die neue Version von Chrome getestet habe* und da stoxx mittlerweile auch das .Net Framework entdeckt hat...

Wie wäre es mit Chrome? Das kennt diese Probleme dank eines modernen Compilers nicht mehr.
Im Gegensatz zu Delphi.Net kann man in Chrome namespaces so verwenden wie sie gedacht waren. (Und muss sich nicht weiterhin mit Dateinamen nerven lassen )

Die Dateinamen sind absolut unerheblich
Erste Datei:
Delphi-Quellcode:
namespace EinNamespace;

interface

type
  Class1 = public class
  private
      fClass2 :Class2;
   public
      property Class2 :Class2 read fClass2;
  end;
  
implementation

end.
Zweite Datei:
Delphi-Quellcode:
namespace EinNamespace;

interface

type
  Class2 = public class
  private
      fClass1: Class1;
  public
      property Class1 :Class1 read fClass1;
  end;
  
implementation

end.
Beide Klassen sind im gleichen Namespace deklariert und man muss rein gar nichts rumbasteln, rumschrauben oder sonstwas umbiegen.
Ich meine genau so sollte es doch sein.


Sicher ist es in solchen Fällen oftmals handlicher gewisse Abstraktionen auf das Wesentliche zu machen.
Aber wenn man es macht, dann nur weil man es will, nicht weil der Compiler zu antiquiert ist.

*Ich fand es übrigens so gut, dass ich es nach 15 Minuten testen gleich gekauft habe.
Nach all den Face lifts seit meiner vorherigen ur-alt-beta Version erscheint mir Chrome sogar mächtiger als C#, hat alle IMHO sinnlosen Beschränkungen von Delphi über Board geworfen. Aber trotzdem diese schlichte Eleganz bewahrt, die Pascal auszeichnet...
  Mit Zitat antworten Zitat
Benutzerbild von stoxx
stoxx

Registriert seit: 13. Aug 2003
1.111 Beiträge
 
#29

Re: Trick um "überkreuzenden Bezug" von Units zu u

  Alt 8. Mai 2005, 14:16
Hi Robert,

Chrome werde ich mir bei Gelegenheit mal angucken. Ich habe zwar die Vorzüge von .NET erkannt, bin aber noch nicht umgestiegen im Moment wäre das zuviel Arbeit.
ABER, was die Sache mit den Überkreuzdeklarationen angeht, habe ich mich entschlossen, den Entwurf überhaupt nicht weiterhin so gestalten zu wollen.
Strebe jetzt strenge Baumhierarchien von OBEN nach UNTEN an. Gegenseitige Objektbekanntschaften vermeide ich, indem ich die Kommunikation von UNTEN nach OBEN ganz normal über Objektreferenzen löse, aber umgekehrt von OBEN nach UNTEN nur noch versuche EVENTS zu nutzen. Somit müssen die Klassen, die in der "Hierarchie" oben stehen, überhaupt keine Objectreferenz mehr haben. Damit entfällt auch das Problem der Überkreuzdeklaration.
Ausserdem auch viel besser wegen Quelltextwiederverwendbarkeit, gegenseitige Abhängigkeiten und so theoretischen Zeugs
Und wenn ichs in Notfällen wirklich mal brauche, werde ich weiterhin rumcasten
bis denn dann
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 3     123   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:56 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz