Circular unit reference umgehen.

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
MAC
Beiträge: 770
Registriert: Sa 21. Feb 2009, 13:46
OS, Lazarus, FPC: Windows 7 (L 1.3 Built 43666 FPC 2.6.2)
CPU-Target: 32Bit

Circular unit reference umgehen.

Beitrag von MAC »

Hallo.

Vorab: Ich weis selber was das für ein Fehler ist und wie ich ihn umgehen kann. ABER mein Ziel ist es: Mehere Klassen in verschiedenen Units haben die auf sich selbst zugreifen. Welches viel übersichtlicher wäre...
Theoretisch wegen den Circular Unit error nicht möglich oder ?

Ich habe es aber geschaft dies mit 3 Units teilweise zu realisieren:

Basic_unit

Code: Alles auswählen

Klasse1 = class
end;
Klasse2 = class
end;
Klasse1Unit

Code: Alles auswählen

uses basic_unit;
Klasse1 = class(basic_unit.Klasse1)
andere:Klasse2;
procedure EineProcedure;
end;
Klasse2Unit

Code: Alles auswählen

uses basic_unit;
Klasse2 = class(basic_unit.Klasse2)
andere: Klasse1;
procedure EineAndereProcedure;
end;
Damit kann man auf die anderen Klassen zugreifen. Dummerweise nicht auf deren Proceduren weil die Proceduren nicht in der basic_unit definiert sind...
Kann man sonnst irgendwie die Klassen in verschiedene Dateien bringen ? (Es würde auch reichen wenn die Implementation in verschiedenen Datein liegt und das interface in einer.)
In manchen fpc units werden include-Datein verwendet ? wäre es damit möglich, leider habe ich keine ahnung wie man diese verwendet...
In dem meisten Fällen klappt die Circular Unit referenc zu umgehen . Einfach den Quellcode der einen Unit in die 2te Einzufügen.
Könnte man nicht Lazarus so erweitern das es die möglichkeit gibt das im Hintergrund automatisch so zu machen , ohne das die ordnun in mehere Datein verloren geht ?

Code: Alles auswählen

Signatur := nil;

Heinrich Wolf
Beiträge: 323
Registriert: Di 12. Apr 2011, 13:21
OS, Lazarus, FPC: WinXP + VMWare Player mit Fedora14, L 1.1, FPC 2.7.1
CPU-Target: 1core 1,8GHz 32Bit
Wohnort: Fürth
Kontaktdaten:

Re: Circular unit reference umgehen.

Beitrag von Heinrich Wolf »

Hallo,

eine Circular Reference hab ich öfters produziert, wenn zwei Forms (2 *.pas und 2 *.lfm Dateien) einander gegenseitig Methoden aufrufen. Das sieht erst mal so aus:

a.pas:

Code: Alles auswählen

unit a;
uses b;
interface
type
a = class(tForm);
...
implementation
...
b.pas:

Code: Alles auswählen

unit b;
uses a;
interface
type
b = class(tForm);
implementation
...
Code zu duplizieren ist dabei eine schlechte Lösung, wenn es in diesem Zusammenhang überhaupt das Problem löst. Die richtige Lösung ist, das circuläre uses Statement in den implementation Block zu verschieben.

a.pas:

Code: Alles auswählen

unit a;
interface
type
a = class(tForm);
...
implementation
uses b;
...
b.pas:

Code: Alles auswählen

unit b;
interface
type
b = class(tForm);
implementation
uses a;
...
Gruß
Heiner

MAC
Beiträge: 770
Registriert: Sa 21. Feb 2009, 13:46
OS, Lazarus, FPC: Windows 7 (L 1.3 Built 43666 FPC 2.6.2)
CPU-Target: 32Bit

Re: Circular unit reference umgehen.

Beitrag von MAC »

Vielen Dank für die Hilfe,
wie ich allerdings erwähnt habe weis ich was eigentlich eine Circular unit Reference ist und das ich es so umgehen könnte.
Problemeatisch wird es nur, Da beide Units auf Code zugreifen der in der Anderen Unit im interface Teil Deklariert ist, deshalb klappt das mit dem unses im Implementation Teil leider nicht.

Bevor ich das "Ordentlich" in 2 units schreiben wollte hatte ich halt beiden Code in einer Unit gehalbt und eine forward Declaration erstellt.
Die Forward deklaration gilt dabei leider nur die die aktuelle unit...

Code: Alles auswählen

Signatur := nil;

Heinrich Wolf
Beiträge: 323
Registriert: Di 12. Apr 2011, 13:21
OS, Lazarus, FPC: WinXP + VMWare Player mit Fedora14, L 1.1, FPC 2.7.1
CPU-Target: 1core 1,8GHz 32Bit
Wohnort: Fürth
Kontaktdaten:

Re: Circular unit reference umgehen.

Beitrag von Heinrich Wolf »

Hi MAC,

ich verstehe nicht ganz, in welchem Zusammenhang Deine Circuläre Referenz auftritt. Alles, was Du in Unit a im Interface Block deklarierst, kannst Du in Unit b verwenden, sobald b ein uses a an der richtigen Stelle enthält. Forward löst andere Probleme.

Gruß
Heiner

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Circular unit reference umgehen.

Beitrag von mse »

Falls es nicht möglich ist die Klassen besser aufzuteilen muss man ein wenig tricksen.

Code: Alles auswählen

uses basic_unit;
Klasse1 = class(basic_unit.Klasse1)
 private
  andere: basic_unit.Klasse2; //ist in tat und warheit klasse2_unit.Klasse2
 public
  procedure EineProcedure;
end;
 
implementation
uses
 klasse2_unit;
 
Klasse1.EineProcedure;
begin
 klasse2_unit.Klasse2(andere).EineAndereProcedure;
end;
Falls solche Sachen notwendig werden ist in aller Regel die unit und Klassen Aufteilung noch nicht ausgereift. ;-)
Ein weiteres Mittel zur Entflechtung sind interface.

Martin

MAC
Beiträge: 770
Registriert: Sa 21. Feb 2009, 13:46
OS, Lazarus, FPC: Windows 7 (L 1.3 Built 43666 FPC 2.6.2)
CPU-Target: 32Bit

Re: Circular unit reference umgehen.

Beitrag von MAC »

danke.

Ich hab es jetzt wie mse gelöst.
Basiert da auf dem was ich oben geschreiben habe nur das die genaue unit im implementation deklariert ist und es einfach als andere Klasse nehme...
(Bzw ich hab ne lokale Procedure (= Procedure nur im implementation Bereich) geschrieben damit ich nicht immer klasse2_unit.Klasse2(andere) sondern Klasse2(andere) verwenden kann...)

Code: Alles auswählen

Signatur := nil;

Antworten