![]() |
class helper generic class
unter
![]() Dh. ich kann keine Unit aufbauen
Delphi-Quellcode:
unit GraphGenericHelperTypes;
interface uses MygenericGraphTypes; type TVertexhelper<T>= class helper for TVertex<T> OutputAttributes: TVertexOutputAttributes; function HasAdditionalAttributes: Boolean end; implementation end. um einen Datentyp TVertex<T> wie in ![]() ich möchte alle Funktionalität der Klassen TVertex<T> = class, TEdge<T, V> = class, .... in einen Bestandteil der nur für die Graph-Mathematik nötig ist und einen Bestandteil der für die Visualisierung via GraphViz ( ![]() Gibt es eine alternative Lösung für dieses Problem in Delphi ? |
AW: class helper generic class
Du hast also sowas wie ein
Delphi-Quellcode:
und so ein Visualisierungsgedöns
TCoreVertex<T> = class
procedure Foo; end;
Delphi-Quellcode:
?
TVertex<T> = class( TCoreVertex<T> )
procedure Bar; end; Oder wie muss ich das verstehen? |
AW: class helper generic class
Es gibt halt keine generischen Class-Helper.
Genauso, wie man keine generischen Prozeduren deklarieren kann. :cry: Man kann maximal einen ungenerischen Class-Helper für einen Generic definieren. |
AW: class helper generic class
der Plan geht wie folgt :
eine Klasse für TVertex nur mit Eigenschaften die eine Vertex auch hat....
Delphi-Quellcode:
und dann gibt es noch
TVertex<T> = class
public /// alles was hier kommt brauche ich für die Graph Mathematik ... ... end;
Delphi-Quellcode:
TVertexhelper<T> = class helper for TVertex<T>
public /// alles was hier kommt brauche ich *** nur **** für die Visualisierung ... ... end; alle Rechenoperationen laufen auf den Basis Klassen TVertex<T>; Wer was zeichnen lassen wir füllt bei Bedarf die Classhelper felder auf. Vererben will ich nicht weil dann alle Algorithmen auch eine Ableitung von TVertex<T> erwarten und dies ist eigentlich unlogisch. |
AW: class helper generic class
Du musst ja auch nicht vererben, sondern du kannst ja auch wrappen.
Diese verlinkte Lib habe ich mir mal angesehen und mal kurz was zusammengefasst
Delphi-Quellcode:
Wenn du jetzt eine andere Funktionalität brauchst, dann baue dir einen Wrapper, der arbeitet dann auch nicht anders als ein class helper.
unit GenericGraph.Global;
interface uses SysUtils, Generics.Collections, GenericGraph.ColorSchemes, Variants; type {$REGION 'Documentation'} /// <summary> /// Definition for a marker, used for edges, vertices and graphs /// </summary> {$ENDREGION} TMarker = Variant; {$REGION 'Documentation'} /// <summary> /// An associative List of Markers /// </summary> {$ENDREGION} TMarkerList = TDictionary<string, TMarker>; TCore = class Marker: TMarkerList; {$REGION 'Documentation'} /// <summary> /// The degree is used in an undirected graph and determined the amount /// of direct neighbours to a vertex /// </summary> {$ENDREGION} Degree: Integer; function HasAdditionalAttributes: Boolean; virtual; destructor Destroy; override; procedure Mark( Key: String; Value: TMarker ); function GetMark( Key: String ): TMarker; function HasMark( Key: String ): Boolean; procedure UnMark( Key: String ); function HasAnyMark( ): Boolean; procedure ClearMarks( ); end; TCore<T> = class( TCore ) Data: T; end; {$REGION 'Documentation'} /// <summary> /// Contains attributes to customize the output of a TVertex /// </summary> {$ENDREGION} TVertexOutputAttributes = record Caption: String; Shape: String; Color: TGraphVizColor; FontColor: TGraphVizColor; FillColor: String; FontSize: Integer; FontName: String; ReverseDirection: Boolean; end; {$REGION 'Documentation'} /// <summary> /// Represents a single vertex in the graph /// </summary> {$ENDREGION} TVertex<T> = class( TCore<T> ) public Name: String; OutputAttributes: TVertexOutputAttributes; {$REGION 'Documentation'} /// <summary> /// The in-degree is used in an directed graph and determines the amount /// of edges entering a vertex /// </summary> {$ENDREGION} DegreeIn: Integer; {$REGION 'Documentation'} /// <summary> /// The out-degree is used in an directed graph and determines the amount /// of edges�leaving a vertex /// </summary> {$ENDREGION} DegreeOut: Integer; function HasAdditionalAttributes: Boolean; override; end; {$REGION 'Documentation'} /// <summary> /// A simple ordered list of vertices /// </summary> {$ENDREGION} TVertexList<T> = class( TList < TVertex < T >> ); {$REGION 'Documentation'} /// <summary> /// Contains attributes to customize the output of a TEdge /// </summary> {$ENDREGION} TEdgeOutputOptions = record Caption: String; Color: String; Style: String; end; {$REGION 'Documentation'} /// <summary> /// Represents a single edge in the graph /// First attribute is the data assigned to the edge /// Second attribute is the data assigned to the vertex (should match your implementation of TVertex<V>) /// </summary> {$ENDREGION} TEdge<T, V> = class( TCore<T> ) VertexA: TVertex<V>; VertexB: TVertex<V>; Directed: Boolean; Degree_Reverse: Integer; Weight: Integer; OutputAttributes: TEdgeOutputOptions; constructor Create( pDirected: Boolean ); function HasAdditionalAttributes( ): Boolean; override; end; TEdgeList<T, V> = class( TList < TEdge < T, V >> ); TGraphOutputOptions = record NodeSep: Double; RenderAsNonDirectedGraph: Boolean; // Added by mc.botha TrueColor, Splines, Overlap: Boolean; BGColor: TGraphVizColor; end; EBasicGraphException = Exception; EDuplicateEdge = class( EBasicGraphException ); implementation { TCore } procedure TCore.ClearMarks; begin FreeAndNil( Marker ); end; destructor TCore.Destroy; begin FreeAndNil( Marker ); inherited; end; function TCore.GetMark( Key: String ): TMarker; begin Result := Null; if Assigned( Marker ) then begin if Marker.ContainsKey( Key ) then Result := Marker.Items[Key]; end; end; function TCore.HasAdditionalAttributes: Boolean; begin Result := False; end; function TCore.HasAnyMark: Boolean; begin Result := False; if Assigned( Marker ) then Result := Marker.Count > 0; end; function TCore.HasMark( Key: String ): Boolean; begin Result := False; if Assigned( Marker ) then Result := Marker.ContainsKey( Key ); end; procedure TCore.Mark( Key: String; Value: TMarker ); begin if not Assigned( Marker ) then Marker := TMarkerList.Create; if Marker.ContainsKey( Key ) then Marker.Items[Key] := Value else Marker.Add( Key, Value ); end; procedure TCore.UnMark( Key: String ); begin Assert( Assigned( Marker ) ); if Marker.ContainsKey( Key ) then Marker.Remove( Key ); if Marker.Count = 0 then FreeAndNil( Marker ); end; { TVertex<T> } function TVertex<T>.HasAdditionalAttributes: Boolean; begin Result := ( Trim( OutputAttributes.Shape ) <> '' ) or ( Trim( OutputAttributes.Caption ) <> '' ) or ( Trim( OutputAttributes.Color ) <> '' ) or ( Trim( OutputAttributes.FontColor ) <> '' ) or ( OutputAttributes.FontSize <> 0 ) or ( OutputAttributes.ReverseDirection ) or ( Trim( OutputAttributes.FontName ) <> '' ); end; { TEdge<T, V> } constructor TEdge<T, V>.Create( pDirected: Boolean ); begin inherited Create; Directed := pDirected; Weight := 1; end; function TEdge<T, V>.HasAdditionalAttributes: Boolean; begin Result := ( Trim( OutputAttributes.Caption ) <> '' ) or ( Trim( OutputAttributes.Color ) <> '' ) or ( Trim( OutputAttributes.Style ) <> '' ); end; end.
Delphi-Quellcode:
So kannst deine Funktionalitäten ziemlich DRY implementieren.
TAbstractWrapper = class
end; TCoreWrapper = class( TAbstractWrapper ) constructor Create( AInstance : TCore ); end; TCoreWrapper<T> = class( TCoreWrapper ) constructor Create( AInstance : TCore<T>; end; TVertexWrapper<T> = class( TCoreWrapper<T> ) constructor Create( AInstance : TVertex<T> ); end; TEdgeWrapper<T,V> = class( TCoreWrapper<T> ) constructor Create( AInstance : TEdge<T,V> ); end; |
AW: class helper generic class
Zitat:
Ich würde doch einfach separate Berechnungsklassen schreiben. Damit bist Du im Endeffekt doch besser dran (finde ich). So eine Klasse kann ja auch statisch sein, sodaß die Instantiierung wegfällt. Bei der Verwenden sieht man dann aber auch genau, wo die Implementierung der Berechnung steht: Procedure
Delphi-Quellcode:
myVertex.DoSomeWeirdAndMagicStuff(someOtherVertix);
// vs. TTheSpecialCalculator.DoSomeWeirdAndMagicStuff(myVertex, someOtherVertix); |
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:07 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz