Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Klassen sollen sich gegenseitig kennen (https://www.delphipraxis.net/174113-klassen-sollen-sich-gegenseitig-kennen.html)

Jumpy 4. Apr 2013 14:00

Klassen sollen sich gegenseitig kennen
 
Hallo,

ich habe in einer Unit zwei Klassen definiert, die sich gegenseitig kennen sollen. Im folgenden nur eine vereinfachte Ausgangsstellung bei der das Problem auftritt, das der Compiler meckert:

Delphi-Quellcode:
TKapitel=class
  private
  Abs:TAbschnitt; //hier meckert der Compiler: Undefinierter Bezeichner TAbschnitt
  end;

TAbschnitt=class
  private
  Kap:TKapitel;
  end;
Wenn das über Units verteilt wäre, wäre das diese zirkuläre Referenz Geschichte, wo ich eine unit im interface und die andere im implementation Teil deklarieren müsste. Aber wieso hier, wo doch alles in einer Unit steht? Ist das weil der Compiler von oben nach unten vor geht? Gäbe es dann sowas wie die Vorwärtsdeklaration bei C auch für Klassen?

Der schöne Günther 4. Apr 2013 14:03

AW: Klassen sollen sich gegenseitig kennen
 
Delphi-Quellcode:
uses
  Generics.Collections;

type
   MyParent = Class;  // This is a forward class definition

  MyChild = Class
  private
    ParentObect:MyParent;
  public
  End;

  MyParent = Class // The MyParent class is now defined
  public
    tlChildren:TList<MyChild>;
  end;

implementation

end.
Quelle:
http://stackoverflow.com/a/2137057

Jumpy 4. Apr 2013 14:31

AW: Klassen sollen sich gegenseitig kennen
 
Cool. Ich hab sowas ja vermutet, aber das lief nicht. Mein Fehler war der selber wie im Stackoverflow-Thread: Ich hab mehr als ein Type benutzt. Danke, auch für den Link.

Witzigerweise ist meine Intention dieselbe, wie beim dortigen Thread-Ersteller nur umständlich mit TObjectList, da noch ohne Generics.

Aphton 4. Apr 2013 16:35

AW: Klassen sollen sich gegenseitig kennen
 
Wie wärs mit
Delphi-Quellcode:
TKapitel = class;
TAbschnitt = class;

TKapitel=class
  private
  Abs:TAbschnitt; //hier meckert der Compiler: Undefinierter Bezeichner TAbschnitt
  end;

TAbschnitt=class
  private
  Kap:TKapitel;
  end;
Nennt sich forward-declaration (Edit: oh das kennst du ja bereits)

Furtbichler 5. Apr 2013 09:25

AW: Klassen sollen sich gegenseitig kennen
 
Klassen, die sich gegenseitig kennen, sind i.A. (also nicht immer!) ein Indikator für schlechtes Design. Ich würde es mit einem Mediator-Pattern versuchen, der zwischen beiden Klassen vermittelt.

Geht das nicht, sind imho Interfaces die sauberere Alternative zu forward-Deklarationen.

Jumpy 5. Apr 2013 11:32

AW: Klassen sollen sich gegenseitig kennen
 
Keine Ahnung ob das in meinem Fall schlechtes Design ist oder eine der Ausnahmen. Meine Kapitel kennen "ihre" Abschnitte. Die Abschnitte müssen erstmal nicht wissen, in welchem Kapitel sie sind. Sie bräuchten also von daher TKapitel erstmal nicht kennen.
Es geht nun aber darum, das ein Abschnitt evtl. erst freigeschaltet wird wenn ein anderes Kapitel beendet wurde. Er muss somit nicht das Kapitel kennen in dem er steckt, also sein Elternobjekt, aber ein anderes Kapitel von dem er ggf. abhängig ist.

Ich hab das Mediator-Pattern mal bei Wikipedia nachgeschaut und es scheint mir für den Fall zu aufwendig, aber da mir da die Erfahrung mangelt täusch ich mich vllt. auch. Man könnte natürlich noch eine weitere Zentrale Klasse erstellen, die entscheidet, wann ein Abschnitt freigegeben wird, die somit sämtliche dafür nötigen Informationen, Verknüpfungen verwaltet, aber das find ich zu aufwendig.

"Ist doch einfacher die Klasse Abschnitt selber zu Fragen, ob sie freigegeben (nicht im Sinne von .Free!!!) ist, die wiederum ihr "Vorgänger"-Kapitel fragt, ob es schon durch ist."

Furtbichler 5. Apr 2013 11:47

AW: Klassen sollen sich gegenseitig kennen
 
Gutes OOP geht nicht immer den Weg des schnellsten Umsetzens, sondern den Weg, was am einfachsten wartbar und erweiterbar ist.

Ich würde eine hierarchische Beziehung aufbauen, da dies den Daten entspricht. Der Mediator wäre dann dafür zuständig, bestimmte Eigenschaften in Abhängigkeit anderer Änderungen anzufassen. Das ist nicht aufwändig. Es wird nur diese eine Funktionalität in eine eigene Klasse verlagert.

Ich würde mir die Mühe machen, das exemplarisch zu implementieren (sofern die Zeit es zulässt und der Chef nicht hinter einem steht).

sx2008 5. Apr 2013 13:16

AW: Klassen sollen sich gegenseitig kennen
 
Zitat:

Zitat von Furtbichler (Beitrag 1210054)
Klassen, die sich gegenseitig kennen, sind i.A. (also nicht immer!) ein Indikator für schlechtes Design.

Volle Zustimmung :thumb:
Zitat:

Zitat von Furtbichler (Beitrag 1210054)
Ich würde es mit einem Mediator-Pattern versuchen...

Ich würde versuchen eine gemeinsame Basisklasse von TKapitel und TAbschnitt zu extrahieren:
Delphi-Quellcode:
TBuchKnoten = class
// Gemeinsamkeiten von TKapitel und TAbschnitt hier rein
...
end;

TAbschnitt=class(BuchKnoten)
  private
    Parent:BuchKnoten; // Elternteil ist meist ein TKapitel (könnte aber auch TKlappentext sein)
  end;

TKapitel=class(BuchKnoten)
  private
   Abschnitt : TAbschnitt;
  end;

Jumpy 5. Apr 2013 14:05

AW: Klassen sollen sich gegenseitig kennen
 
Zitat:

Zitat von Furtbichler (Beitrag 1210077)
Ich würde mir die Mühe machen, das exemplarisch zu implementieren (sofern die Zeit es zulässt und der Chef nicht hinter einem steht).

Das ist ein internes Projekt ohne Eile, an dem ich immer mal arbeite, wenn nichts für Kunden ansteht. Dadurch wird es wahrscheinlich mehr Zeit kosten, als es nachher tatsächlich einspart. Aber da die Leute deren Zeit das einspart ein paar Gehaltsstufen über mir stehen, rechntets sich ja vllt. doch irgendwann.
Gleichzeitig ist das für mich aber auch eine Übung auch mal komplexere Modelle umzusetzen, weswegen mir eure Anregungen schon sehr recht sind.

sx2008s Vorschlag ist auch interessant, da ein Abschnitt sowohl von einem früheren Kapitel als auch einem früheren Abschnitt abhängig sein kann (bisher gelöst durch ein Feld für vorherigen Abschnitt und eines für vorheriges Kapitel). Mit dem Basis-Klassen-Gedanken, könnte ich natürlich stattdessen eine Liste vom Typ Basisklasse verwalten und da sowohl Kapitel als auch Abschnitt reinschieben und wäre später noch offen dafür, dass mal die Anforderung kommt von mehreren Kapiteln oder Abschnitten abhängig zu sein und dann brauch ich die Klasse nicht wieder umbauen.

Gleichzeitig ist mir aber eben auch der Gedanke gekommen das andersherum aufzuziehen, sprich der Vorgänger-Abschnitt bzw. das Kapitel bekommt eine Liste von Nachfolgern, die es benachrichtigen soll, wenn sich sein Status (ungelesen->gelesen) ändert. Worauf diese dann ihren Status auf freigegeben ändern können.

Ich muss da mal das WE drüber nachdenken.


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