Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Kreuzende Beziehung zw. zwei Objekten (https://www.delphipraxis.net/133147-kreuzende-beziehung-zw-zwei-objekten.html)

SebE 26. Apr 2009 21:15


Kreuzende Beziehung zw. zwei Objekten
 
Hallo Delphi-/Pascal-Programmierer.

Ich hab weniger ein Problem, als eine allgemeine Frage.

Wie implementiere ich zwei Objekte, die jeweils eine Beziehung zum Anderen pflegen?

Beispiel:

Delphi-Quellcode:
type
  A = class
  private
    <list of B>

    [...]
    end;

type
  B = class
  private
    myA: A;

    [...]
    end;
A und B sind in unterschiedlichen Modulen (zB: mA, mB).

ist es in irgend einer Weise möglich, dass zu realisieren, oder muss ich beide Definitionen in eine Type-Klausel (also in EIN Modul) beschreiben?

Gegen das "Ein-Modul-Konzept" spricht meine Philosophie, jedes Objekt in seine eigene Unit.
(Type-Casting auf untypisierte Pointer kommt aus stilistischen Gründen nicht in Frage)

Ich sehe selbst leider keine Möglichkeit, aber ich will es nicht unversucht lassen und frage deshalb euch :-)

Ich hoffe, ihr könnt mir Tipps geben

Vielen Dank an euch

mkinzler 26. Apr 2009 21:17

Re: Kreuzende Beziehung zw. zwei Objekten
 
Einfach die Unit von B in den Uses einbinden

mirage228 26. Apr 2009 21:18

Re: Kreuzende Beziehung zw. zwei Objekten
 
Kommt auf die Beziehung an. Eventuell kannst Du Abstrakte Klassen oder Interfaces in eine dritte Unit auslagern...

Edit:
Zitat:

Zitat von mkinzler
Einfach die Unit von B in den Uses einbinden

So wie ich sein Problem verstanden habe, würde so eine zirkuläre Referenz enstehen, was Delphi so nicht erlaubt.

Satty67 26. Apr 2009 21:22

Re: Kreuzende Beziehung zw. zwei Objekten
 
Hatte das gleiche Problem. Wollte es auch in eigenen Units lassen und habe es wie oft im VCL-Quellcode gelöst.

Pointer auf TObject ubergeben und Gültigkeit vorm Cast via Classname abfragen. Das ist kaum besser als untypisierte Pointer, aber ich hab' nach langem suchen auch keinen anderen Weg gefunden.

stoxx 26. Apr 2009 21:36

Re: Kreuzende Beziehung zw. zwei Objekten
 
man hat ja Hoffnung, dass wenn sie jetzt den 64 Bit Compiler eh neu machen müssen, dass dieser Quatsch endlich mal in Delphi behoben wird.

Und alle Meinungen, die man sogar gelegentlich hört, es wäre sogar ein Feature statt ein Failure, (manche behauptetn ja sogar, dass dann was mit dem klassenkonzept nicht stimmen würde) sind auch nur halbherzig. Denn in einer einzigen Unit funktioniert es ja, dass man überkreuzende Bezüge zu Klassen herstellen kann, warum also nicht auch in verschiedenen Units, für mich ist da kein Unterschied.
Es führt dazu, dass man viel zu viel Quelltext in eine einzige Unit stecken muss. Modularisierung wäre schon toll...

stoxx 26. Apr 2009 21:39

Re: Kreuzende Beziehung zw. zwei Objekten
 
ich benutze gelegentlich diese Lösung. So wird zumindest der Quellcode durch die unschönen Casts nicht belastet und bleibt damit befreit von unwichtigen Sachen. Meine Meinung ist, es sollte möglichst nur das in einer Funktion stehen, was wirklich zum funktionieren der Funktion wichtig ist.


http://www.delphipraxis.net/internal...euzender+bezug

SebE 26. Apr 2009 21:43

Re: Kreuzende Beziehung zw. zwei Objekten
 
@mirage228:

Ja, die Idee kam mir auch (ist auch vom Stil her elegant):

Hat man nur noch eine Klasse (und ein Modul) mehr :-(

Danke euch für die schnellen Antworten:

Für die Vollständigkeit:

Delphi-Quellcode:
type
  A1 = class
    [...]
    end;
Delphi-Quellcode:
type
  B = class
    <list of A1>

    [...]
    end;
Delphi-Quellcode:
type
  A2 = class(A1)
    myB: B;

    [...]
    end;


Gibt es in Delphi abstrakte Klassen (wär der Wahnsinn!)???

mirage228 26. Apr 2009 21:45

Re: Kreuzende Beziehung zw. zwei Objekten
 
Zitat:

Zitat von SebE
Gibt es in Delphi abstrakte Klassen (wär der Wahnsinn!)???

Also soweit ich weiß kannst Du nur "normale" Klassen mit abstrakten Methoden machen (ala TStrings), sowas wie "type TKlasse = abstract class" gibt es meines wissens nach (zumindest für Win32) noch nicht...

SebE 26. Apr 2009 21:46

Re: Kreuzende Beziehung zw. zwei Objekten
 
@stoxx:

Dieses "forward"-Deklarieren ist zwar hilfreich, aber entspricht nicht dem Ansatz: Erst Deklarieren, dann nutzen.

Wie erstelle ich abstrakte Klassen (man könnte ja den Constructor virtual abstract definieren -> nicht sehr elegant)

SebE 26. Apr 2009 21:49

Re: Kreuzende Beziehung zw. zwei Objekten
 
@mirage228:
NOCH nicht?
in Pascal gab's die mal, also kann man davon ausgehen, dass es sie auch in Zukunft nicht mehr geben wird (schade eigentlich).

mkinzler 26. Apr 2009 21:53

Re: Kreuzende Beziehung zw. zwei Objekten
 
In Delphi kann man Klassen mit abstrakten Methoden trotzdem instantiieren. Erst beim Zugriff auf eine nicht implemnetierte Methode wird dann eine Exception ausgelöst.

mirage228 26. Apr 2009 21:55

Re: Kreuzende Beziehung zw. zwei Objekten
 
Zitat:

Zitat von SebE
NOCH nicht?
in Pascal gab's die mal, also kann man davon ausgehen, dass es sie auch in Zukunft nicht mehr geben wird (schade eigentlich).

Es ist nur möglich einzelne Methode mit "virtual; abstract" zu vershen (Beispiel: TStrings) - für die gesamte Klasse (wie z.B. bei Java) ist es nicht möglich.
Mit "noch nicht" meinte ich, dass dieses Feature ja evtl. in späteren Versionen hinzugefügt wird...

stoxx 26. Apr 2009 21:57

Re: Kreuzende Beziehung zw. zwei Objekten
 
reine Neugier, was kann man mit abstrakten Klasse machen, was man mit abstrakten Methoden nicht realisieren kann?

mkinzler 26. Apr 2009 22:01

Re: Kreuzende Beziehung zw. zwei Objekten
 
Eine Ableitung erzwingen. Dürfte aber für dieses Problem nicht entscheidend sein.

stoxx 26. Apr 2009 22:06

Re: Kreuzende Beziehung zw. zwei Objekten
 
Zitat:

Zitat von SebE
@stoxx:

Dieses "forward"-Deklarieren ist zwar hilfreich, aber entspricht nicht dem Ansatz: Erst Deklarieren, dann nutzen.

ist dieser Ansatz in Zeiten der Entwurfsmuster noch sinnvoll?
und warum hat dann Delphi nichts dagegen, Units im Implementationsteil dann doch wieder gegenseitig zu überkreuzen und eine Abhängigkeit herzustellen. Wenn es doch so gewollt ist, hätte man das doch auch unterbinden müssen, oder nicht?
Also doch eher eine Compilerschwäche (oder Stärke) .. ist halt schneller beim compilieren.

SebE 26. Apr 2009 22:19

Re: Kreuzende Beziehung zw. zwei Objekten
 
@stoxx:
mir persönlich gefällt diese (erlaubte) Kreuzverwendung überhaupt nicht.

Zitat:

Zitat von mkinzler
Eine Ableitung erzwingen. Dürfte aber für dieses Problem nicht entscheidend sein.

...aber für die Lösung.
Man kann bei der (abstrakten) Klasse A1 (aus meinem Beispiel) davon ausgehen, dass A2 verwendet wird.

mkinzler 26. Apr 2009 22:22

Re: Kreuzende Beziehung zw. zwei Objekten
 
War Antwort auf Frage von stoxx

stoxx 26. Apr 2009 22:28

Re: Kreuzende Beziehung zw. zwei Objekten
 
Zitat:

mir persönlich gefällt diese (erlaubte) Kreuzverwendung überhaupt nicht.
Warum nicht? Was ist daran so schlimm, wenn man seinen Code in mehrere Dokumente verteilt?
Ein Motor im Auto kann man auch herausnehmen. Klar, alleine ohne Auto kann man damit nix anfangen, aber zumindest ist er austauschbar.

Auch Deine Graphikkarte im Computer ist alleine nicht verwendbar, trotzdem kann man sie getrennt vom Computer lagern, wenn man dies möchte.


@ War Antwort auf Frage von stoxx

ah Danke .. da entfallen ja dann die Messageboxen mit der Angabe des Klassennamens, wenn man mal wieder eine virtual abstracte Methode vergessen hat zu programmieren :)

SebE 26. Apr 2009 22:34

Re: Kreuzende Beziehung zw. zwei Objekten
 
Hab ich schon einmal geschrieben.
Ich verfolge eine strikte Philosophie:
Erst sagen, wie etwas aussieht, bevor man es verwendet.

dieses Prinzip (wie es der Delphi-Compiler verwendet), dass man innerhalb des SELBEN Type-Konstruktes Kreuz-Deklarationen erzeugen darf, geht NOCH in Ordnung, da man dies Überschauen kann. Aber dieses Prinzip auf ganze Module angewandt, ist unübersichtlich und darf nicht erlaubt sein.

mkinzler 26. Apr 2009 22:41

Re: Kreuzende Beziehung zw. zwei Objekten
 
Lässt sich aber nicht verhindern.

Panthrax 26. Apr 2009 22:46

Re: Kreuzende Beziehung zw. zwei Objekten
 
1.
Delphi-Quellcode:
type
  TAbstract = class abstract
    // abstrakte Klasse.
  end;
2. Wie soll die Klassengröße beim Kompilieren bestimmt werden, wenn sich Typdefinitionen zikulär über mehrere Dateien verwenden? Das geht nicht, nicht mit Einzellaufkompilern. Und das Konzept ist gut so, wie es ist! -- mM.

mirage228 26. Apr 2009 22:49

Re: Kreuzende Beziehung zw. zwei Objekten
 
Zitat:

Zitat von Panthrax
1.
Delphi-Quellcode:
type
  TAbstract = class abstract
    // abstrakte Klasse.
  end;

Seit welcher Version geht das? Unter Delphi 7 / 2005 geht es noch nicht...

SebE 26. Apr 2009 22:51

Re: Kreuzende Beziehung zw. zwei Objekten
 
bei abstrakten Klassen spielt die benötigte Größe gar keine Rolle.

Panthrax 26. Apr 2009 22:54

Re: Kreuzende Beziehung zw. zwei Objekten
 
Zitat:

Zitat von mirage228
Zitat:

Zitat von Panthrax
1.
Delphi-Quellcode:
type
  TAbstract = class abstract
    // abstrakte Klasse.
  end;

Seit welcher Version geht das? Unter Delphi 7 / 2005 geht es noch nicht...

Turbo Delphi Explorer, Delphi 2009.

Zitat:

Zitat von SebE
bei abstrakten Klassen spielt die benötigte Größe gar keine Rolle.

Natürlich tut sie das...

SebE 26. Apr 2009 23:07

Re: Kreuzende Beziehung zw. zwei Objekten
 
ok, wir reden hier sicher von verschiedenen Schuhen.

Erklär mir das bitte näher: in wiefern benötigt ein Compiler die Größe einer abstrakten Klasse?
Und für die "richtige" (abgeleitete) Klasse kennt er doch die abstrakte Klasse.

Panthrax 26. Apr 2009 23:19

Re: Kreuzende Beziehung zw. zwei Objekten
 
Zitat:

Zitat von SebE
ok, wir reden hier sicher von verschiedenen Schuhen.

Erklär mir das bitte näher: in wiefern benötigt ein Compiler die Größe einer abstrakten Klasse?
Und für die "richtige" (abgeleitete) Klasse kennt er doch die abstrakte Klasse.

Zwei Beispiele in einem:
Delphi-Quellcode:
type
  TAbstract = class abstract
    // Größe = GrößeVon(Felder neu in TAbstract) + GrößeVon(Vorfahre(TAbstract))
    //       = GrößeVon(Felder neu in TAbstract) + GrößeVon(TObject)
  end;

  TConcrete = class(TAbstract)
    // Größe = GrößeVon(Felder neu in TConcrete) + GrößeVon(Vorfahre(TConcrete))
    //       = GrößeVon(Felder neu in TConcrete) + GrößeVon(TAbstract)
  end;
Und jetzt für zwei abstrakte Klassen, die sich gegenseitig verwenden: (Schenk' ich mir...)

Abstrakte Klasse können nicht instantiiert werden. Der Klassenzusatz "abstract" hat nur disziplinarische Wirkung, vergleichbar mit Sichtbarkeitsbeschränkungen. Insofern unterscheiden sich abstrakte Klassen nicht von "gewöhnlichen" Klassen. Die Größe ist für alle gleichsam bedeutsam.

SebE 26. Apr 2009 23:24

Re: Kreuzende Beziehung zw. zwei Objekten
 
DAnke für die Aufklärung...ich hab mich gewundert, warum du dich so speziell auf abstrakte Klassen fest gelegt hast. Das ist doch (wie du richtig schreibst) wurst, ob Abstrakt oder nicht...


Also: Es ist doch kein Problem von Abstrakten Klassen, dass man deren Größe nicht berechnen kann (das ist ein allgemeines Problem) - das ist der Grund für meinen Einwand.

brechi 26. Apr 2009 23:43

Re: Kreuzende Beziehung zw. zwei Objekten
 
Delphi-Quellcode:
type
  THallo = class;

  THuhu = class
    a: THallo;
  End;

  THallo = class
    a: THuhu;
  end;
ist das nicht das was ihr sucht?

oder waren 2 units gemeint?

Panthrax 26. Apr 2009 23:46

Re: Kreuzende Beziehung zw. zwei Objekten
 
Zitat:

Zitat von SebE
DAnke für die Aufklärung...ich hab mich gewundert, warum du dich so speziell auf abstrakte Klassen fest gelegt hast. Das ist doch (wie du richtig schreibst) wurst, ob Abstrakt oder nicht...

Also: Es ist doch kein Problem von Abstrakten Klassen, dass man deren Größe nicht berechnen kann (das ist ein allgemeines Problem) - das ist der Grund für meinen Einwand.

Man kann die Größe berechnen. -- Natürlich muss man die Größe (abstrakter) Klassen berechnen können. Eben das ist gewährleistet durch das Konzept von Delphi und auch in einer Güte, die einen Einzellaufkompiler ermöglicht. Deshalb kann man keine beliebigen Beziehungen über mehrere Quelltextmodule (hier: Dateien) erstellen. (Auch Mehrlaufkompiler können das nur bedingt.) Der Grundsatz: "Erst definieren, dann verwenden." passt wunderbar hier hinein und hilft außerdem beim Denken. Und innerhalb eines Quelltextmoduls ist es dennoch durch Vorausdeklarationen möglich, dass Klassen sich gegenseitig verwenden. Objektvariablen sind in ihrer Größe nämlich definiert. (Sie sind Zeiger, siehe oben "THallo = class;" = SizeOf(Pointer)) Das gilt eben nicht für beliebige Typen:
Delphi-Quellcode:
type
  TAbstract = class {abstract}
    FField: TAnyType;
  end;

SebE 26. Apr 2009 23:49

Re: Kreuzende Beziehung zw. zwei Objekten
 
ne, die Lösung steckt in einer übergeordneten (wär schön, wenn noch abstrakten) Klasse.

Ja, es sind mehrere Units im Spiel.

SebE 26. Apr 2009 23:56

Re: Kreuzende Beziehung zw. zwei Objekten
 
@Panthrax:

Hui viel Text, bitte nicht denken, ich widerspreche dir...wir sind schon einer Meinung (ich weiß, wie ein Compiler funktioniert), nur ich habe deine Aussage anders aufgefasst.

Es geht um das Problem der Unmöglichkeit der Bestimmung der Größe von "zirkulären" Klassen. Nur ist das eben kein spezielles Problem von abstrakten Klassen, sondern von Allen.

Panthrax 27. Apr 2009 00:21

Re: Kreuzende Beziehung zw. zwei Objekten
 
Zitat:

Zitat von SebE
ne, die Lösung steckt in einer übergeordneten (wär schön, wenn noch abstrakten) Klasse.

Es spricht nichts dagegen es so zu tun. Es muss eben nur in einer Datei geschehen.

Wenn man verstehen will, warum das so ist, oder es gar für eine Kompilerschwäche hält (wie oben von jemandem erwähnt) kann sich die Kompilertechnik ansehen und darf gern Verbesserungsvorschläge an die Kompilertechniker machen. :glaskugel:

Zitat:

Zitat von SebE
@Panthrax: (...) Es geht um das Problem der Unmöglichkeit der Bestimmung der Größe von "zirkulären" Klassen. Nur ist das eben kein spezielles Problem von abstrakten Klassen, sondern von Allen.

Genau. Es betrifft eben nicht nur Klassen. Das beste Beispiel ist vielleicht dieses hier, das auch direkt einleuchtet, weil es weder mit einer noch mehreren Quelltextmodulen funktioniert:
Delphi-Quellcode:
// "Unit 1"
type
  TRec1 = record // TAnyType1
    Rec2: TRec2;
  end;

// "Unit 2"
type
  TRec2 = record // TAnyType2
    Rec1: TRec1;
  end;

alzaimar 27. Apr 2009 06:42

Re: Kreuzende Beziehung zw. zwei Objekten
 
Zitat:

Zitat von brechi
Delphi-Quellcode:
type
  THallo = class;

  THuhu = class
    a: THallo;
  End;

  THallo = class
    a: THuhu;
  end;
ist das nicht das was ihr sucht?

Ja, aber SebE und Panthrax sind zu sehr mit sich selbst beschäftigt. :zwinker:

Panthrax 27. Apr 2009 07:15

Re: Kreuzende Beziehung zw. zwei Objekten
 
Zitat:

Zitat von alzaimar
Ja, aber SebE und Panthrax sind zu sehr mit sich selbst beschäftigt. :zwinker:

Da hat wohl einer noch Schlaf in den Augen...

SebE 27. Apr 2009 07:15

Re: Kreuzende Beziehung zw. zwei Objekten
 
Ich hab mich (abgewandelt) zitiert.
Für mich die (bisher) beste Lösung:

Zitat:

Zitat von "SebE
...
Für die Vollständigkeit:

Delphi-Quellcode:
type
  A1 = class
    [...]
    end;
Delphi-Quellcode:
uses
  mA1;

type
  B = class
    <list of A1>

    [...]
    end;
Delphi-Quellcode:
uses
  mA1, mB;

type
  A2 = class(A1)
    myB: B;

    [...]
    end;
...

Alle liegen in ihrem eigenen Modul.


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