Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi F2047 Zirkuläre Unit-Referenz ? (https://www.delphipraxis.net/124762-f2047-zirkulaere-unit-referenz.html)

daredd 24. Nov 2008 21:25


F2047 Zirkuläre Unit-Referenz ?
 
Kann mir einer sagen was der Compiler damit meint:

[DCC Fehler] NewClient.pas(7): F2047 Zirkuläre Unit-Referenz auf 'NewClient'


???
THX

s.h.a.r.k 24. Nov 2008 21:27

Re: F2047 Zirkuläre Unit-Referenz ?
 
du hast halt eine zirkuläre referenz. also... du hast 2 units. du referenzierst in der unit1 unter uses unit2 und in der unit2 in der uses-klausel die unit1, also wie folgt:
Delphi-Quellcode:
// das hier steht in der Unit1.pas
unit Unit1;

uses
  Unit2;

{ ... }

// das hier steht in der Unit2.pas

unit Unit2;

uses
  Unit1;
das darf nicht sein, warum sollte klar sein oder?! was soll der compiler denn machen?! was zuerst einbinden?!

mkinzler 24. Nov 2008 21:27

Re: F2047 Zirkuläre Unit-Referenz ?
 
Weil du Unit1 in Unit2 und umgekehrt einbindest. Entweder gemeinsames auslagern oder einmal im Interface und einmal in der Implementierung einbinden

oki 24. Nov 2008 21:30

Re: F2047 Zirkuläre Unit-Referenz ?
 
Solltest du in einer der Units auf Elemente der anderen Unit nur im Implementation-Teil zugreifen kannst du das Problem damit lösen, dass du diese Unit mit uses hinter implementation einbindest.

Noch alles klar?

Gruß oki

daredd 24. Nov 2008 21:32

Re: F2047 Zirkuläre Unit-Referenz ?
 
ah stimmt danke, hab das total vergessen! habe jetzt in der unit2 die unit1 unter implementations als uses, und es geht!

omata 24. Nov 2008 22:34

Re: F2047 Zirkuläre Unit-Referenz ?
 
Nur weil etwas geht ist es noch lange nicht sinnvoll.

Die Hinweise, die hier gegeben wurden sind zwar richtig, allerdings nicht sinnvoll.
Solche Zirkelschlüsse sind niemals nötig, wenn man so etwas braucht, hat man etwas grundlegendes falsch gemacht.

Sven M. 26. Nov 2008 07:57

Re: F2047 Zirkuläre Unit-Referenz ?
 
Könntest du da mal ein Beispiel nennen? Ich meine, ich habe zwar noch nie zirkulär referenziert, wüsste auch nicht, warum man das machen sollte. Interessieren würde mich aber trotzdem, warum man da was "grundlegendes falsch" gemacht hat...

Hawkeye219 26. Nov 2008 09:47

Re: F2047 Zirkuläre Unit-Referenz ?
 
Hallo Sven,

das Problem bei dieser Art der Programmierung ist, dass du ein undurchsichtiges Netz von Verknüpfungen erstellst, das nur sehr schlecht zu testen und zu warten ist. Das Ersetzen einer Unit ist unter Umständen mit Änderungen in mehreren anderen Units verbunden, wodurch sich neue Fehler einschleichen können.

Bei einer streng hierarchischen Struktur kann ein Test des Programms "von unten" erfolgen. Du fängst mit den Units an, die keine Abhängigkeiten besitzen. Nachdem diese Units getestet wurden, kannst du dich den Teilen zuwenden, die die getesteten Units referenzieren. Beim Netz mit zirkulären Referenzen weißt du von keiner Unit, ob sie tatsächlich korrekt arbeitet, weil du das Netz nur als Ganzes testen kannst.

Gruß Hawkeye

Sven M. 26. Nov 2008 10:48

Re: F2047 Zirkuläre Unit-Referenz ?
 
Hi Hawkeye,
das leuchtet ein. Besten Dank - wieder was gelernt!:)

hanspeter 26. Nov 2008 10:48

Re: F2047 Zirkuläre Unit-Referenz ?
 
Zitat:

Zitat von Sven M.
Könntest du da mal ein Beispiel nennen? Ich meine, ich habe zwar noch nie zirkulär referenziert, wüsste auch nicht, warum man das machen sollte. Interessieren würde mich aber trotzdem, warum man da was "grundlegendes falsch" gemacht hat...

Beispiel:

Ein Datasource für den Datenbankzugriff

Ein Datasource für Reportfunktionen.
Die Reportfunktionen benötigen Connection aus Datasource.

In Datasource wird lediglich ein Zeiger auf den Report declariert, also

Report : TReport;

Ziel ist es von der Datenbankschicht Initialisierungen im Reportteil vornehmen zu können.

Schon hat man ein zirkulären Bezug.

In Net (auch Oxygene) geht so etwas.
Die Ursache das das in Delphi nicht geht, ist der altmodische Einpasscompiler, der solche Bezüge nicht auflösen kann.

Gruß Peter

mkinzler 26. Nov 2008 10:53

Re: F2047 Zirkuläre Unit-Referenz ?
 
Es geht in Delphi ja. Ist aber ( auch in C# usw. ) nicht sauber.

oki 26. Nov 2008 16:11

Re: F2047 Zirkuläre Unit-Referenz ?
 
Zitat:

Zitat von omata
Nur weil etwas geht ist es noch lange nicht sinnvoll.

Die Hinweise, die hier gegeben wurden sind zwar richtig, allerdings nicht sinnvoll.
Solche Zirkelschlüsse sind niemals nötig, wenn man so etwas braucht, hat man etwas grundlegendes falsch gemacht.

Hi omata,

das zirkuläre Bezüge grundsätzlich zu vermeiden sind, aus allen hier benannten Gründen und noch vielen mehr, ist unbestritten. Zu behaupten, dass das nicht sinnvoll ist halte ich aber für Falsch. Leider läßt sich das auch bei sauber Strukturierung nicht immer vermeiden.

Ein Beispiel:

Du proggst ein eigenes Control, dass auf seiner Oberflächen einen Button für ein eigenes Property-Form hat. Somit beinhaltet die Unit in der du deine Komponente schreibst einen Bezug auf die Property-Form-Unit. Diese benötigt jetzt aber einen Bezug auf deine Komponenten, wenn sofort nach dem ändern eines Wertes die Komponente direkt aktualisiert werden soll ohne das Fenster zu schließen.

Dann bin ich gezwungen die Unit der Form im Implementationteil einzubinden, da das Formular ja durch die Komponente kreiert wird. Die Unit der Komponente binde ich im interface-Teil der Form ein, da ich die Instanz des Controls für die Wertezuweisung im Formular brauche.

Die zirkulären Bezüge in diesem Bsp. sind glücklicherweise überschaubar und imho zu verkraften. Wenn du da eine bessere Lösung anbieten kannst, schau ich mir gerne an.

Gruß oki

mjustin 26. Nov 2008 16:53

Re: F2047 Zirkuläre Unit-Referenz ?
 
Zitat:

Zitat von mkinzler
Es geht in Delphi ja. Ist aber ( auch in C# usw. ) nicht sauber.

Es geht, wenn man immer alles in eine einzige Unit packt :spin2:

Wenn man jede Klasse in eine eigene Unit packt, und die Klassen sich wechselseitig referenzieren, weil das halt im Objektmodell (fachliches oder Domänenmodell) so ist, kommt man in Delphi leider nur mit Klimmzügen ans Ziel.
Sauber sind gegenseitige Bezüge im Prinzip schon, und in C#, Java und anderen Sprachen mit später Bindung zum Glück auch problemlos möglich.

Anderes Beispiel: es gibt keinen Weg, das Visitor-Pattern der Gang of Four zu implementieren, wenn die beteiligten Klassen in verschiedenen Units stehen, und man ohne Typecasts arbeiten will.

oki 26. Nov 2008 17:02

Re: F2047 Zirkuläre Unit-Referenz ?
 
... und selbst mit Typecast muss die Klasse bekannt sein und somit die Unit in der sie definiert ist eingebunden werden.

Gruß oki

omata 26. Nov 2008 19:58

Re: F2047 Zirkuläre Unit-Referenz ?
 
Zitat:

Zitat von oki
Du proggst ein eigenes Control, dass auf seiner Oberflächen einen Button für ein eigenes Property-Form hat. Somit beinhaltet die Unit in der du deine Komponente schreibst einen Bezug auf die Property-Form-Unit. Diese benötigt jetzt aber einen Bezug auf deine Komponenten, wenn sofort nach dem ändern eines Wertes die Komponente direkt aktualisiert werden soll ohne das Fenster zu schließen.

Ich würde ja gerne etwas genaueres dazu sagen, allerdings erschliesst sich mir diese Gedankenwelt leider nicht.

Deshalb ganz kurz: Ich würde da eigene Events für schreiben, dann ist auch hier kein Zirkelschluss nötig.

oki 26. Nov 2008 21:16

Re: F2047 Zirkuläre Unit-Referenz ?
 
Hi omata,

ok, dann mit Events, Kein Problem. Und welche Klassenreferenz übergibst du dann um eine spezielle Eigenschaft deiner Klasse zu setzen?

Gruß oki

omata 26. Nov 2008 21:30

Re: F2047 Zirkuläre Unit-Referenz ?
 
Zitat:

Zitat von oki
Und welche Klassenreferenz übergibst du dann um eine spezielle Eigenschaft deiner Klasse zu setzen?

Self, oder Referenzparameter über den Methodenzeiger.

oki 26. Nov 2008 21:42

Re: F2047 Zirkuläre Unit-Referenz ?
 
Sorry omata, ich glaube wir reden aneinander vorbei. Gib mal ein Beispiel für deine Version.

Hier meine:
Delphi-Quellcode:
unit MyClasses;

interface

type
  TCustomClass = class(TCustomControl)
....


implementation

uses CustomPropertyForm;

...
procedure TCustomClass.ShowPropertyForm;
var PropForm : TPropertyForm;
begin
  PropForm := TPropertyForm.create(nil);
  PropForm.Item := self;
  PropForm.Show;
end;
Delphi-Quellcode:
unit CustomPropertyForm;

interface

uses MyClasses;

type
  TPropertyForm = class(TForm)
  ...
  public
    property Item : TCustomClass read FItem write SetItem;
  ...
Gruß oki

omata 26. Nov 2008 22:05

Re: F2047 Zirkuläre Unit-Referenz ?
 
Natürlich kannst du hier ein Minimalbeispiel liefern, indem du so einen starken Knebel ansetzt, so dass man da gar keinen anderen Ausweg, als einen Zirkelschluss sieht.
Aber das war ja gerade mit "grundlegend" gemeint, kann man das was man erzeugen will auch strukturiert realisieren? Das war und ist die Intention, und da kann man ganz klar sagen, das geht und zwar immer. Es muss keine Frikellösung her. Das ist nicht nötig. Natürlich muss man dann einen Moment länger über die Lösung nachdenken.

Also muss hier erstmal klar werden, was im Großen möglich sein soll, sonst kann hier natürlich keine sinnvolle Lösung gezeigt werden.

Zum Beispiel: Warum kann die Property auch überschrieben werden? Wäre es da nicht besser den Kontruktur zu überschreiben und den Item somit fest zu initialisieren und nur einen lesenden Zurgiff von außen zu gestatten? Aber das soll jetzt nicht vom eigentlichen Problem ablenken.

Ich muss zugeben, ich sehe noch keinen Sinn in dieser Struktur, das liegt aber wohl nur daran, dass ich bis jetzt solch eine Struktur nicht benötigt habe. Oder aber es liegt einfach daran, dass ich solche Strukturen anders löse und deshalb gar nicht weiss, dass dies hier jetzt eine solche, gewünschte Struktur erfordert.

Also, es kann sehr gut sein, dass wir aneinander vorbeireden.

Gruss
Thorsten

stoxx 27. Nov 2008 02:41

Re: F2047 Zirkuläre Unit-Referenz ?
 
hier gibts eine recht praktikable Lösung für Sonderfälle, wo es sich mal nicht vermeiden lässt, oder wo einzelne Klassen mal doch nicht hierarchisch gestaltet werden wollen ..


http://www.delphipraxis.net/internal...highlight=unit

oki 27. Nov 2008 06:47

Re: F2047 Zirkuläre Unit-Referenz ?
 
Moin omata,

zur Sicherheit vorweg. Falls jemand den Eindruck haben sollte ich will streiten, is nicht so. Sollte der nächste Satz zu hart klingen, positiv sehen.
So, du umschreibst immer schön wortreich, das das nie nötig ist. Auf konkrete Beispiele zeigst du aber keine neue Herangehensweise. Ich hab das Beispiel jetzt mal schnell hingetippt. Da mach ich mir keine tieferen Gedanken, ob das Property readonly und der Constructor überschrieben sein sollte. Hier geht es darum, ob sich zirkuläre Bezüge grundsätzlich immer vermeiden lassen. Ich habe auch nicht irgendein Stück Code hingeschrieben wo das dann auch einfach nur so ist, sondern im Vorfeld erläutert, um welchen Ansatz es geht.
Da ich auch nicht den Stein der Weisen gefunden habe, bin ich gerne bereit an dieser Stelle zu lernen. Aber dann bitte mit konkreten Lösungsvorschlägen. Wie löse ich das Problem, wenn eine Klasse durch eine eigene procedure sein Eigenschaftenfenster aufruft, (von mir aus auch eine mitgegebene Fensterinstanz) in der seine Eigenschaften angezeigt und verändert werden können. Dabei helfen Aussagen wie
Zitat:

Aber das war ja gerade mit "grundlegend" gemeint, kann man das was man erzeugen will auch strukturiert realisieren? Das war und ist die Intention, und da kann man ganz klar sagen, das geht und zwar immer. Es muss keine Frikellösung her. Das ist nicht nötig. Natürlich muss man dann einen Moment länger über die Lösung nachdenken.
Dann bitte her mit der Lösung. Von mir auch grundlegend. Du darfst auch gerne länger nachdenken.

Manchmal habe ich so viele eigene Klassen, dass ich für die Übersicht diese in einzelne Units auslager. Selten, aber manchmal, nehme ich dann zähneknirschend einen Zirkulären Bezug in Kauf. Der Vorteil der Übersichtlichkeit überwiegt.

Um es nochmal klar zu stellen, ich halte zirkuläre Bezüge für keine gute Sache und versuche sie generell zu vermeiden. Auf jedes Beispiel pauschal mit denk dir was besseres aus zu antworten ohne konkrete Lösungsansätze zu bringen halte ich für nicht richtig. Helfen tut es auch keinem. Nebenbei bemerkt hab ich festgestellt, dass sich auch in älteren Threads Mitglieder mit diesem Thema beschäftigt haben, denen ich so einiges zutraue.

Also omata, so sehr ich deine fachlichen Hinweise in anderen Threads schätze, bitte keine hoch gestochenen Pauschalweisheiten, sondern konkrete Strategie-, Design- und Lösungsansätze. Und wenn es für die angeführten Beispiele ist.

Gruß oki

omata 27. Nov 2008 16:14

Re: F2047 Zirkuläre Unit-Referenz ?
 
Liste der Anhänge anzeigen (Anzahl: 1)
...

oki 27. Nov 2008 17:46

Re: F2047 Zirkuläre Unit-Referenz ?
 
Hi omata,

schau ich mir heute Abend an, versprochen.

Gruß oki

oki 27. Nov 2008 22:08

Re: F2047 Zirkuläre Unit-Referenz ?
 
Hi omata

Klar, wenn ich das Formular aus der Hauptanwendung starte, dann erledigt sich das natürlich mit dem zirkulären Bezug. Mir ging es hier aber explizit um den Aufruf des Formulars aus der Klasse heraus. Natürlich gebe ich dir recht, dass es immer (fast immer; kann mich da nicht fest legen) einen Weg gibt das zu umgehen. Ich habe aber Situationen gehabt, da war es einfacher und sinnvoller einen zirkulären Bezug in Kauf zu nehmen.

Ich denke mal, dass ich meine Aussage entschärfe. Zirkuläre Bezüge können vermieden werden, sind aber unter speziellen Umständen akzeptabel.

Dann gute Nacht und Gruß

oki

omata 27. Nov 2008 23:06

Re: F2047 Zirkuläre Unit-Referenz ?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von oki
Klar, wenn ich das Formular aus der Hauptanwendung starte, dann erledigt sich das natürlich mit dem zirkulären Bezug. Mir ging es hier aber explizit um den Aufruf des Formulars aus der Klasse heraus.

Ohne da jetzt noch weiter drauf rumzureiten...

Trotzdem nochmal ein neues Beispiel.
Und das meinte ich mit "grundlegend", wenn ich soetwas machen möchte, warum nicht das Control als Form auslegen?

nicodex 28. Nov 2008 08:26

Re: F2047 Zirkuläre Unit-Referenz ?
 
Letzendlich kann man sich immer in einer dritten Unit eine (abstrakte) Schnittstelle definieren.
Die Frage ist nur, ob sich der Aufwand immer lohnt. Wenn die Möglichkeit besteht, dass die Funktionalität irgendwann getrennt, verändert oder erweitert wird, dann sollte man sich die Arbeit machen.


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