AGB  ·  Datenschutz  ·  Impressum  







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

class helper generic class

Ein Thema von bernhard_LA · begonnen am 7. Dez 2014 · letzter Beitrag vom 8. Dez 2014
 
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#5

AW: class helper generic class

  Alt 8. Dez 2014, 06:51
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:
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.
Wenn du jetzt eine andere Funktionalität brauchst, dann baue dir einen Wrapper, der arbeitet dann auch nicht anders als ein class helper.
Delphi-Quellcode:
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;
So kannst deine Funktionalitäten ziemlich DRY implementieren.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
 


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:14 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-2025 by Thomas Breitkreuz