Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - TreeMap Ersatz für Delphi?


Nano-Ware - Mi 11.04.12 14:04
Titel: TreeMap Ersatz für Delphi?
Hey,

ich suche einen Variablentyp, den Delphi von Haus aus unterstützt. Der Key soll vom Typ String sein, Value ein eigener Typ (TMeineKlasse). Ich möchte nun z.B. per Map1.get("KLASSE1") das Objekt "ebay : TMeineKlasse" und bei Map1.get("KLASSE2") das Objekt "amazon : TMeineKlasse" zurückbekommen. Ich hoffe ihr versteht was ich meine.

Danke


Narses - Mi 11.04.12 14:10

Moin!

Suchst du TStringList (.Strings[] / .Objects[])? :gruebel: :nixweiss:

cu
Narses


bummi - Mi 11.04.12 14:14

Suchst Du etwas in der Art?

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,printers, StdCtrls;

type
  TMyClass=Class(TPersistent)
    Procedure Showinfo;
  End;
  TMyClass2=Class(TPersistent)
    Procedure Showinfo;
  End;
 


  TForm2 = class(TForm)
    Button2: TButton;
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form2: TForm2;

implementation
{$R *.dfm}



Function GetClass(const S:String):Tobject;
  begin
    Result := FindClass(s).Create;
  end;


{ TMyClass2 }

procedure TMyClass2.Showinfo;
begin
   Showmessage('Ich bin Klasse2')
end;

{ TMyClass }

procedure TMyClass.Showinfo;
begin
   Showmessage('Ich bin Klasse1')
end;
procedure TForm2.Button2Click(Sender: TObject);
begin
  TMyClass( GetClass('TMyClass')).ShowInfo;
end;

initialization
RegisterClasses([TMyClass,TMyClass2]);


end.


Nano-Ware - Mi 11.04.12 14:16

Hmm. Wie benutze ich das? Ich brauche ein Objekt, wie es in Java die TreeMap ist:

private Map<String, MyClass> tape = new TreeMap<String, MyClass>();

Dann schreibe ich einen Eintrag:

tape.put("Objekt1", MyClass1);

und kann es dann später durch den Key wiederbekommen:

tape.get("Objekt1");

Danke


bummi - Mi 11.04.12 14:22

Du kannst ja noch eine eine Tapeklasse drumbasteln

Delphi-Quelltext
1:
2:
3:
4:
Procedure put(const S:String;var C:TPersistent);
begin
  C := FindClass(s).Create;;
end;


das Get hast Du ja schon ... > GetClass


Nano-Ware - Mi 11.04.12 14:29

Okay ich glaube ich erkläre es blöd. Bei einem Array ist es doch normalerweise so:

0 -> "Hallo"
1 -> "Bello"
2 -> "Hund"

Das bedeutet einem Index(Integer) ist ein Wert(String) zugeordnet.

Was ich jetzt will ist, dass nicht nur der Datentyp String variable ist (man kann ja auch Integer oder Char Arrays erzeugen) sondern auch der Indexwert. Also zB :

"SLNachbarn" -> nachbarn
"SLEltern" -> eltern

Hier ist jetzt der Index quasi String und der Wert eine Variable vom Typ "TStringList". Das ganze muss allerdings auch andersrum funktionieren, dass wir einem Index vom Typ TStringList einen String als Wert zuweisen.

Ich hoffe ich habe es nun besser erklärt.


Martok - Mi 11.04.12 14:44

Deine Erklärung wird immer verworrener, aber deinen Java-Code würde ich so ähnlich abbilden:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
type
  TMyBaseClass = class of TMyBase;
  TMyBase = class
    constructor Create; virtual;
  end;
  TMyClass1 = class(TMyBase)
    constructor Create; override;
  end;

procedure TForm1.Button1Click(Sender: TObject);
var
  map: TStringList;
  c: TMyBaseClass;
begin
  map:= TStringList.Create;
  map.AddObject('key1', TObject(TMyClass1));
  //weitere Keys
  c:= TMyBaseClass(map.Objects[map.IndexOf('key1')]);
  c.Create;
end;
Achtung: Beispielcode, mindestens 2 Speicherlecks und keinerlei Fehlerprüfung (ungültige Keys) ;)

Genau genommen würde ich eine Klasse von T(Hashed)StringList ableiten, die die Konvertierung macht und bei Fehlern nil zurückgibt. Kann man ja gleich einen generic für nehmen.

Ich bin der Meinung dass das auch mal ohne virtuellen Konstruktor ging, aber scheint nicht so. Ging allerdings in Freepascal neulich auch schon nur so, vielleicht erinnere ich mich also falsch.

EDIT: hab grad deinen letzten Absatz nochmal gelesen und vermute jetzt, dass das immer noch nicht das ist was du willst. Sowas hat man aber schnell programmiert - wenn man generics hat, sonst weniger schnell aber immer noch einfach ;)


Nano-Ware - Mi 11.04.12 14:52

Dort wird ja ein TObject eingetragen, bzw eine Klasse. Was ich aber will ist, dass zB

map.AddObject('key1', TObject(TMyClass1));

hier eine gefüllte StringList übergeben wird, die ich dann durch den Key wieder bekomme und auslesen kann.


EDIT:

TDictionary<TKey,TValue>


Nersgatt - Mi 11.04.12 15:10

Also für mich klingt das wie TDictionary:

Delphi-Quelltext
1:
map : TDictionary<String, TMeineKlasse>;                    


jaenicke - Mi 11.04.12 15:12

Richtig, hat er ja auch schon editiert. Und da muss man auch nix mehr programmieren, das ist alles schon fertig (@user profile iconMartok ;-)).


Nersgatt - Mi 11.04.12 15:24

Das ist einer der Gründe, warum ich Generics so mag. Es nimmt mit einen Haufen Routinearbeit ab.


Martok - Mi 11.04.12 16:26

Ah, ich hab damit gerechnet dass Embadingsda die offensichtliche Anwendung nicht mitliefert. Oder sie alternativ so verbuggt ist dass man sie nicht benutzen kann.


Nano-Ware - Mi 11.04.12 16:38

Okay das Funktioniert. Ich brauche allerdings auch noch eine normale Liste. Also eine List von irgendeinem Typ (am besten wie bei TDictionary durch <Typ>) die eine Add()-Funktion, Remove()- und Clear()-Funktion hat.


SvenAbeln - Mi 11.04.12 16:49

user profile iconNano-Ware hat folgendes geschrieben Zum zitierten Posting springen:
Ich brauche allerdings auch noch eine normale Liste. Also eine List von irgendeinem Typ [...]

Wie wäre es mit TList<T>?


Nersgatt - Mi 11.04.12 18:16

user profile iconSvenAbeln hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconNano-Ware hat folgendes geschrieben Zum zitierten Posting springen:
Ich brauche allerdings auch noch eine normale Liste. Also eine List von irgendeinem Typ [...]

Wie wäre es mit TList<T>?

Oder TObjectList<T>, wenn man den Komfort von OwnsObjects haben möchte.


Nano-Ware - Mi 11.04.12 19:14

Danke


jaenicke - Mi 11.04.12 21:09

Du kannst auch einfach mal in den Quelltext der Unit Generics.Collections schauen. Da findet sich noch einiges mehr an Standard-Klassen und auch einiges Interessante zur Anwendung von Generics an sich.

Die Klassen sind an sich auch gut geschrieben. Die einzige wirkliche Schwäche ist die, die sich durch die ganze VCL und RTL zieht: Man kann sie kaum erweitern, da schlicht viele Methoden nicht als virtuell deklariert sind, bei denen es eigentlich sehr sinnvoll gewesen wäre. Aber das kennt man ja schon als Delphi-Entwickler, dass in der Richtung leider einiges im Argen liegt. Sei es durch versteckte Variablen und Klassen in der implementation-Sektion oder eben privaten und unerreichbaren oder unveränderbaren Feldern und Methoden...