AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Zirkuläre Unit Reference

Ein Thema von Koolance · begonnen am 24. Nov 2006 · letzter Beitrag vom 28. Nov 2006
Antwort Antwort
Seite 2 von 3     12 3      
Koolance

Registriert seit: 28. Feb 2006
Ort: Kerpen
74 Beiträge
 
Delphi 6 Enterprise
 
#11

Re: Zirkuläre Unit Reference

  Alt 24. Nov 2006, 16:08
Nachdem ich zunächst dachte alle wird gut, musste ich feststellen das nur die geerbten Methoden und Eigenschaften übernommen werden (bei den Anderen Fehlermeldung: "Undefinierter Bezeichner")

Also habe ich zum test nicht mehr geerbt, nun kriege ich aber die Fehlermeldung: "Typ ... nicht vollständig definiert"

Die Fehlermeldung lässt sich so umgehen:
Delphi-Quellcode:
type
  TClass1 = class end;

  TClass2 = class
    FClass1: TClass1;
  end;

  TClass1 = class
    FClass2: TClass2;
  end;
Aber so sieht Delphi die Klasse leider als leere Klasse und ich kriege die Fehlermeldung: "Undefinierter Bezeichner"
  Mit Zitat antworten Zitat
Sidorion

Registriert seit: 23. Jun 2005
403 Beiträge
 
#12

Re: Zirkuläre Unit Reference

  Alt 24. Nov 2006, 16:48
ohne das end bei der Forward-Deklaration. Sonst denkt Delphi, die Klasse ist komplett, also so:
Delphi-Quellcode:
Type
  TFoo=Class;
  
  TBar=Class
   FFoo: TFoo;
  End;

  TFoo=Class
   FBar: TBar;
  End;
Manchmal sehen Dinge, die wie Dinge aussehen wollen mehr wie Dinge aus, als Dinge
<Esmerelda Wetterwachs>
  Mit Zitat antworten Zitat
Koolance

Registriert seit: 28. Feb 2006
Ort: Kerpen
74 Beiträge
 
Delphi 6 Enterprise
 
#13

Re: Zirkuläre Unit Reference

  Alt 24. Nov 2006, 17:04
Das habe ich ja schon probiert. Passend zu dem Quelltext käme jetzt: Typ TFoo nicht vollständig definiert.

Ich habe ein kleines Beispiel gemacht.
Angehängte Dateien
Dateityp: zip beispiel_800.zip (7,9 KB, 5x aufgerufen)
  Mit Zitat antworten Zitat
xaromz

Registriert seit: 18. Mär 2005
1.682 Beiträge
 
Delphi 2006 Enterprise
 
#14

Re: Zirkuläre Unit Reference

  Alt 24. Nov 2006, 22:50
Hallo,

ich habe Dir schon in meinem letzten Beitrag geschrieben, wie es geht. In Deinem Beispielcode deklarierst Du die beiden Klassen in verschiedenen Units, bzw. schreibst in der einen Unit eine Forward-Deklaration auf eine Klasse in einer anderen Unit. Das funktioniert natürlich nicht. Wenn Du Forward-Deklaration nutzt ("type TFoo = class;"), dann musst Du diese Klasse auch komplett in dieser Unit deklarieren.

Gruß
xaromz
I am a leaf on the wind - watch how I soar
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

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

Re: Zirkuläre Unit Reference

  Alt 25. Nov 2006, 09:19
Präziser:

Forward Deklarationen eines Types müssen im gleichen "Type" Block erfolgen samt ihrer vollständigen Deklaration. Ein regülärer Bezeichner auf Unitebene beendet eines Type Block automatisch. Ein regulärer Unitbezeichner sind "Unit", "uses", "implementation" und "interface". Ergo: mit Delphi gehen keine Forward Deklarationen über Unitgrenzen hinweg, noch in unterschiedlichen Type-Blöcken.

Erweitere mal virtuell in Gedanken alle Sachen wie "const", "type", "implementation", "interface" nit einem sofortigem "begin end;" Block. Denn defakto existieren diese quasi im Compiler auch wenn wir sie nicht im Source schreiben müssen/dürfen. Dh. nach einem "type" stände sofort "begin end;" und dazwischen kannst du Forward Deklaration machen wie du möchtest Hauptsache du deklarierst diese Typen dann in diesem Block auch vollständig. Eine Deklaration innerhalb dieses "virtuellen" Bereiches ist nicht in anderen "Bereichen" sichtbar.

Einzigste Ausnahme speziell auf den Bezeichner "type" bezogen ist die Deklaration eines neuen eigenständigen Standarddatentyps abgeleitet von einem anderen Datentyp, also sowas:

Delphi-Quellcode:

type
//begin

   TTime = type TDateTime;
   TDate = type TDateTime;

   MyInteger = type Integer;

//end;

type
//begin

//end;
Gruß Hagen
  Mit Zitat antworten Zitat
Koolance

Registriert seit: 28. Feb 2006
Ort: Kerpen
74 Beiträge
 
Delphi 6 Enterprise
 
#16

Re: Zirkuläre Unit Reference

  Alt 27. Nov 2006, 15:28
Das Problem ließ sich mit noch ein bisschen externer hilfe lösen.
Es müssen zu den einzelnen Klassen Interfaces erstellt, und in einzelne Units gepackt werden.
Ich habe für ein Beispiel geschrieben und für alle Interessierten in den Anhang gepackt.

@xamroz
Mein Problem war das es mir sehr wichtig ist die Unitunterteilung aufrecht zu erhalten. Ich dachte es wäre so möglich...
Angehängte Dateien
Dateityp: zip test_114.zip (239,9 KB, 12x aufgerufen)
  Mit Zitat antworten Zitat
xaromz

Registriert seit: 18. Mär 2005
1.682 Beiträge
 
Delphi 2006 Enterprise
 
#17

Re: Zirkuläre Unit Reference

  Alt 27. Nov 2006, 17:01
Hallo,
Zitat von Koolance:
Das Problem ließ sich mit noch ein bisschen externer hilfe lösen.
Es müssen zu den einzelnen Klassen Interfaces erstellt, und in einzelne Units gepackt werden.
Ich habe für ein Beispiel geschrieben und für alle Interessierten in den Anhang gepackt.
Ich hoffe, Du weißt, was Du da tust. Interfaces sind eine sehr fehlerträchtige Sache. Insbesondere durch die gegenseitige Abhängigkeit der beiden Interfaces wirst Du vermutlich ein Speicherleck bekommen. Für diesen Zweck sind Interfaces

Zu Deinem Demoprogramm:
- Du castest ein Interface auf das zugrundeliegende Objekt. Das ist nicht zulässig.
- Du benutzt Objekte, ohne Instanzen zu erzeugen. Das fliegt Dir bald um die Ohren.

Gruß
xaromz
I am a leaf on the wind - watch how I soar
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

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

Re: Zirkuläre Unit Reference

  Alt 27. Nov 2006, 17:22
Neben den korrekten Bemerkungen von Xaromz noch als Bemerkung zusätzlich:

Das was du in deinem Testprojekt machts geht auch einfacher

Delphi-Quellcode:

unit class1;

interface

type
  TClass1 = class
  private
    FClass2: TObject;
  public
    procedure BlaBla;
  end;

implementation

uses class2;

procedure TClass1.BlaBla;
begin
  (FClass2 as TClass2).BlaBla;
end;

unit class2;

interface

type
  TClass2 = class
  private
    FClass1: TObject;
  public
    procedure BlaBla;
  end;

implementation

uses Class1;

procedure TClass2.BlaBla;
begin
  (FClass1 as TClass1).BlaBla;
end;
Gruß hagen
  Mit Zitat antworten Zitat
Koolance

Registriert seit: 28. Feb 2006
Ort: Kerpen
74 Beiträge
 
Delphi 6 Enterprise
 
#19

Re: Zirkuläre Unit Reference

  Alt 27. Nov 2006, 18:00
Dieser Weg soll der sauberere sein, die andere Möglichkeit wäre alles von einem Basisobjektabzuleiten, dann statt dem Interface über das Basisobjekt die Typen zu deklarieren, und am ende wie bei dem Interface zu casten.

@xaromz
[qoute]Ich hoffe, Du weißt, was Du da tust. Interfaces sind eine sehr fehlerträchtige Sache. Insbesondere durch die gegenseitige Abhängigkeit der beiden Interfaces wirst Du vermutlich ein Speicherleck bekommen. Für diesen Zweck sind Interfaces [/quote]

Ich werde wie gesagt den Quellcode erzeugen, also muss ich es nur einmal richtig hin bekommen, und alle interfaces sind richtig.

Zitat:
- Du castest ein Interface auf das zugrundeliegende Objekt. Das ist nicht zulässig.
- Du benutzt Objekte, ohne Instanzen zu erzeugen. Das fliegt Dir bald um die Ohren.
Warum ist das casten unzulässig?
In meinem echten Projekt werden selbst verständlich alle Objekte instanziiert.

@NegaH
Du leitest statt von dem Interface von TObject ab, habe heute keine Zeit mehr das zu testen, werde ich aber auch ausprobieren. Hat es Nachteile?
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

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

Re: Zirkuläre Unit Reference

  Alt 28. Nov 2006, 01:10
Nein, hat keine Nachteile (mein Vorschlag oben), mal davon abgesehen das deine ganze Objektorientierte Konstruktion insich falsch sein muß.

Wenn du über solche Sachen wie oben mein Typcast oder den Interfaces herangehen musst dann stimmt irgendwas nicht an deinem Grundkonzept.

Xaromz hat aber insofern Recht, das

1.) der Weg über die Interfaces ein unnötiger Überbau darstellt da wie in meinem Beispiel das Ganze auch ohne Interfaces geht
2.) du die Verwendung von Interfaces und Klassen nicht vermischen solltest da ansonsten das automatische Referencecounting und somit die Speicherfreigabe durcheinander kommt
3.) der Typcast eines Interfaces direkt in das implementierende Objekt in deinem Source vollkommen falsch ist
4.) der Typcast eines Interfaces in sein implementierendes Objekt grundsätzlich gegen die Regeln, bzw. dem Sinn der Interfaces ist

Wenn du schon eine Referenz von einem Interface auf sein implementierendes Objekt erhalten möchtest dann so:

Delphi-Quellcode:

type
  IMyInterface = interface
    function Implementor: TInterfacedObject;
  end;

  TMyImplementor = class(TInterfacedObject, IMyInterface)
    function Implementor: TInterfacedObject;
  end;

function TMyImplementor.Implementor: TInterfacedObject;
begin
  Result := Self;
end;

// oder gleich so, da Result -> EAX und Self -> EAX
function TMyImplementor.Implementor: TInterfacedObject;
begin
end;
Aber!! zum Widersinnigen der Sache:

Interfaces sollen die Implementierung einer Funktionalität im Zusammenhang mit dessen Schnittstellen Deklaration vollständig voneinander trennen. Es soll also keinerlei Zusammenhang zwischen einer deklarierten Schnittstelle zu der eigentlichen Implementierung dieser Schnittstelle bestehen, vollkommene Abstraktion der verschiedenen Schichten eines Denkmodelles das zur "idealen" Black Box führt.

Führt man aber wie oben in die Schnittstelle = Interface wieder eine Schnittstelle auf den Implementor-> TMyInterfcae ein so durchbricht man diese strikte Logik und macht die Anwendung der Interfaces sinnnlos.

Denn die Deklaration von IMyInterface oben bedeutet das diese Schnittstelle nur durch ein Objekt kompatibel zur Klasse TInterfacedObject durchgeführt werden kann. Diese Restriktion soll aber gerade mit Interfaces strikt vermieden werden.

Ergo: ein normaler OOP Ansatz wie in meinem letzten Posting erreicht exakt das Gleiche wie der Vorschlag über die Interfaces. Nur mit dem Unterschied

1.) das es Typsicher ist und somit sauber, wir eben keinen harten und typ-unsicheren Cast verwenden wie in deinen Sourcen
2.) ohne Umwege funktioniert und somit zusätzliche Fehlerquellen beseitigt. Bedenke die schlimmsten Fehler liegen immer im Konzept eines Modelles !
3.) kein Hilfsmittel misbraucht das für ganz andere Aufgaben gedacht ist, hier eben die Interfaces, und somit die spätere Verwenung deines Modelles für andere "korrekt denkende" Programmierer unmöglich macht. Denn für diese Programmierer ist es ein Unding wie du Interfaces mißbrauchen möchtest.

Grundsätzlich wird man aber deine Problemstellung durch pure OOP und konzeptionelle Änderungen lösen können. Statt mit 2 Units zu arbeiten musst du OOP konform dein Klassenkonzept umstellen und mit 3 Unit arbeiten.

1. Unit -> Basisunit die eine abstrakte Vorfahrklasse enthält in der alle Gemeinsamkeiten der Nachfahrklassen deklariert wurden, meistens abstrakte Klassen. Sprich Klassen aus reiner Deklaration von abstrakten virtuellen Methoden ohne reale Implementierung.

2. Unit -> Nachfahre Class1 von der Basisklasse und Verwendung von UnitClass2 in der Implementation Sektion dieser Unit.

3. Unit -> Nachfahre Class2 von der Basisklasse und Verwendung von UnitClass1 in der Implementation Sektion dieser Unit.

Zitat:
Dieser Weg soll der sauberere sein,...

Ich werde wie gesagt den Quellcode erzeugen, also muss ich es nur einmal richtig hin bekommen, und alle interfaces sind richtig.
Wenn du davon überzeugt bist warum fragst du dann noch ? Ich meine, und damit bin ich nicht der Einzigste hier, das du mit dieser Meinung schon von vornherein deinen größten Fehler begehst. Begründungen siehe oben.

Gruß hagen
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


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 13:09 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