![]() |
Warum TStrings erstellen mit TStringList.Create?
Auszug aus der Turbo-Delphi-Hilfe, Thema "Eine neue Stringliste erstellen":
Delphi-Quellcode:
So Leute, heut bin ich wieder am Grübeln. :gruebel: Immer wieder begegnen mir Codes, in denen Variablen als TStrings deklariert, aber mit TStringList.Create erstellt werden!? In dem obigen Beispiel wird, außer in dem Code-Schnipsel, auch noch im Beschreibungstext explizit darauf hingewiesen:
procedure TForm1.Button1Click(Sender: TObject);
var TempList: TStrings; { Liste deklarieren } begin TempList := TStringList.Create; { Listenobjekt erzeugen } try { Stringliste verwenden } ...
Code:
Gibt es dafür einen Grund, dass TStringList-en als TStrings deklariert werden? Spricht etwas dagegen, eine TStringList auch mit TStringList zu dekalrieren? Was ist besser? :spin2:
So erstellen Sie langlebige Stringlisten:
1. Fügen Sie in der Unit-Datei für das Hauptformular Ihrer Anwendung ein Feld des Typs TStrings in die Formulardeklaration ein. 2. ... Guido. Edit: Mir ist bekannt, dass TStrings die Basisklasse, und TStringList davon abgeleitet ist. :smile2: |
Re: Warum TStrings erstellen mit TStringList.Create?
TStrings ist die abstrakte Basisklasse von TStringList
Du kannst den Typ natürlich auch alsn TStringList deklariere |
Re: Warum TStrings erstellen mit TStringList.Create?
Oder besser gesagt: TStrings ist eine abstrakte Basisklasse, welche eine gemeinsame Schnittstelle bietet und selber keine Speicherverwaltung hat.
TStringList ist ein Nachfahre davon ... es gibt noch andere Nachfahren (wie sich z.B. eine hinter .Lines eines TMemo versteckt) Wenn du selber die TempList nur als TStringList verwendest und sie nicht weitergibst, dann kannst du sie auch direkt als TStringList deklarieren und hast dann auch direkten Zugriff auf spezielle Erweiterungen der TStringList. |
Re: Warum TStrings erstellen mit TStringList.Create?
Ich meine neulich mal etwas bzgl. (Abwärts-)Kompatibilitätsgründen (der Delphi-IDEs) gelesen zu haben, finde es aber leider nicht mehr :gruebel:
|
Re: Warum TStrings erstellen mit TStringList.Create?
Zitat:
Zitat:
Zitat:
Zitat:
Guido. |
Re: Warum TStrings erstellen mit TStringList.Create?
Zitat:
wenn du z.B. diese Prozedur erstellst,
Delphi-Quellcode:
dann kannst du ihr alle Nachfahren von Strings übergeben.
procedure MyProc(List: TStrings);
also z.B. TStringList oder TMemoStrings (die interne virtuelle Stringliste des Memos, mit Umleitung zur Memokomponente von Windows) Wenn man jetzt sowas macht,
Delphi-Quellcode:
dann kann man dieser Funktionen nur noch eine TStringList und deren Nachfahren übergeben,
procedure MyProc(List: TStringList);
aber z.B. kein Memo.Lines mehr. Zitat:
|
Re: Warum TStrings erstellen mit TStringList.Create?
Zitat:
Das hab ich auch gerade getestet. Das eine (TStrings übergeben, wenn TStringList verlangt wird) wird verweigert, während das umgekehrte funktioniert. Zitat:
|
Re: Warum TStrings erstellen mit TStringList.Create?
Ok, bleibt immer noch die Ausgangs-Frage: Warum eine Variable als TStrings deklarieren, wenn mit TStringList instanziert wird?
|
Re: Warum TStrings erstellen mit TStringList.Create?
Zitat:
darum kann man es auch an alles übergeben, welches TStrings "verlangt" TString kann nicht alles, welches TStringList kann, darum kann man es auch nicht an etwas übergeben, welches "mindestens" das verlangt, was auch eine TStringList kann. |
Re: Warum TStrings erstellen mit TStringList.Create?
Dann ist ja wohl TStringlist der größere Eimer :stupid:
|
Re: Warum TStrings erstellen mit TStringList.Create?
Zitat:
|
Re: Warum TStrings erstellen mit TStringList.Create?
Code:
In X passen also nur Menschen, Männer und Frauen rein
Lebewesen > Mensch > Mann > Frank
> Daniel > Frau > Hund > Pudel > Dackel var X: Mensch; Y: Lebewesen; Procedure Toilette(Tür: Mann); und in Y dagegen auch noch die Tiere. Auf dieses Klo dürfen auch NUR die Männer und demnach geht sozusagen Folgendes:
Delphi-Quellcode:
bei dem
Toilette(Frank);
Delphi-Quellcode:
könnte es sich eventuell auch um eine Frau handeln und wer möchte denn, daß die uns was abguckt? :zwinker:
Toilette(Mensch);
|
Re: Warum TStrings erstellen mit TStringList.Create?
@himitsu: Interessant, dass du die "Frau" bei den "Menschen" eingeordnet hast!? *grins* :drunken:
Zitat:
Zitat:
Ein größerer Eimer (Nachfahre) kann das beinhalten, was ein kleinerer Eimer (Basisklasse) beinhaltet. Nichtsdestotrotz wieder zurück zum eigentlichen Thema, das immer noch nicht gelöst ist: Warum eine Variable als TStrings deklarieren, wenn mit TStringList instanziert wird? Guido. |
Re: Warum TStrings erstellen mit TStringList.Create?
Zitat:
|
Re: Warum TStrings erstellen mit TStringList.Create?
@himitsu: in deinem Beispiel wären "Frank" und "Daniel" aber Instanzen von TMann und nicht Ableitungen. Oder was bilden denn Daniel und Frank denn noch neues aus? Ein viertes Bein? Wenn es natürlich Mutanten sind, dann wären es Ableitungen.
|
Re: Warum TStrings erstellen mit TStringList.Create?
Zitat:
Falls ich jedoch blind bin und eine Antwort schlichtweg übersehe, oder du sie erkennen kannst, dann bitte sag sie mir. Und um Missverständnissen vorzubeugen: Bitte nicht in Form von ![]() Guido. |
Re: Warum TStrings erstellen mit TStringList.Create?
TStrings ist eine abstrakte Klasse, hierin wird ein (Soll-)Verhalten festgelegt
TStringList ist eine Klasse, die das vorgegebene Verhalten implementiert. Es gibt aber auch andere Implementierungen (ein Beispiel hat Frank schon genannt) Wenn man den Typ einer Variablen nun auf TStrings festlegt, kann man hier Referenzen auf Objekte verschiedenster Ableitungen/Implementierungen ablegen; TStringList limitiert auf die eine Implementierungen ( und Nachfahren dieser) |
Re: Warum TStrings erstellen mit TStringList.Create?
@Muetze1:
Delphi-Quellcode:
TLebewesen = class
Körper: TFettpolstermitknochen; ... end; TMann = class(TLebewesen) Eier: TSchrumpeldinger; Penis: TGlied; ... end; TFrau = class(TLebewesen) Hirn: TSchuhtick; Mumu: TSagichnicht; ... end; TFrank = class(TMann) Persönlichkeit: TFranksPersönlichkeit; ... end; Zitat:
Zitat:
|
Re: Warum TStrings erstellen mit TStringList.Create?
Zitat:
Edit: Schreibfehler korrigiert. |
Re: Warum TStrings erstellen mit TStringList.Create?
Zitat:
Delphi-Quellcode:
und hier x nur als Tstringlist verwendet und niemals nicht
var x:TStringList;
begin x:=TStringlist.create; ... end; eine andere Klasse (abgeleitet von TStrings) in x verwendet, dann ist es völlig sinnlos TStrings zu nehmen und in der Hilfe auch unsauber erklärt. --> Hier wäre x besser als TStringlist deklariert. Wenn du nirgends Probleme (mit dem Compiler) damit bekommst ist es auch in Ordnung TStringList zu verwenden. Mit TStrings würdest du dir Möglichkeiten verbauen, die vorhanden sind, du aber auf Grund der Deklaration nicht weist wo (Die Möglichkeit der Sortierung hat TStrings IMHO noch nicht dabei etc. pp). Wo nimmt man nun TStrings? Möglichkeit 1 (Wurde schon mehrfach hier erwähnt ): -> Parameter Du hast eine Methode, welche als Parameter TStrings bekommt
Delphi-Quellcode:
Du kannst in dieser Methode verschiedene Ableitungen von TStrings bekommen und bspw. nur die Strings auslesen und - wie hier - anzeigen. Ob das jetzt eine TStringList ist oder Memostrings oder von einem Stringgrid oder eine eigene Ableitung von TStrings ist völlig egal. Durch die virtualisierung des Getters von Strings wird bei jeder Variante intern eine andere Methode aufgerufen, nur du bekommst immer einen String vom Index 0 zurück.
procedure myClass.myMethod(x:TStrings)
begin showmessage(x.Strings[0]); end; Möglichkeit 2 -> Unterschiedliche Instanzierung von TStrings Du bist dir bei der Deklaration noch nicht sicher welche Variante du von TStrings nimmst (das entscheidet sich quasi erst zur Laufzeit):
Delphi-Quellcode:
Hier mal noch ein Beipsiel:
var x:TStrings;
begin if irgendetwas=irgendetwasanders then x:=TStringlist.create else x:=Memo1.lines; end; ... end;
Delphi-Quellcode:
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; type TmyStrings = class(TStrings) protected function Get(Index: Integer): string; override; function GetCount: Integer; override; public function Add(const S: string): Integer; override; procedure Delete(Index: Integer); override; procedure Insert(Index: Integer; const S: string); override; procedure Clear; override; end; TForm1 = class(TForm) Memo1: TMemo; RadioGroup1: TRadioGroup; //mit 3 Einträgen Edit1: TEdit; Button1: TButton; //eintragen des Edits in ausgewählte Impl. von TStrings Button2: TButton; //Anzeige der Stringlist procedure RadioGroup1Click(Sender: TObject); procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private-Deklarationen } FStrings:TStrings; FmyStrings:TmyStrings; FStringList:TStringList; public { Public-Deklarationen } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.RadioGroup1Click(Sender: TObject); begin //Übergabe einer konkreten Implementierung an FStrings case RadioGroup1.ItemIndex of 0: FStrings:=Memo1.lines; 1: FStrings:=FmyStrings; 2: FStrings:=FStringList; else FStrings:=nil; end; end; procedure TForm1.Button1Click(Sender: TObject); begin //eigentliche Verwendeung von FStrings if assigned(FStrings) then FStrings.Add(edit1.Text); end; procedure TForm1.Button2Click(Sender: TObject); begin //Anzeige der StringList showmessage(FStringlist.Text); end; procedure TForm1.FormCreate(Sender: TObject); begin //ein paar Initialisierungen FStringList:=TStringlist.Create; FmyStrings:=TmyStrings.Create; end; { TmyStrings } function TmyStrings.Add(const S: string): Integer; begin //es wird in dem Programm ausschließlich add verwendet showmessage(s); result:=-1; end; procedure TmyStrings.Delete(Index: Integer); begin //abstrakte Methode überschreiben end; function TmyStrings.Get(Index: Integer): string; begin //abstrakte Methode überschreiben raise Exception.create('Keine Strings gespeichert'); end; function TmyStrings.GetCount: Integer; begin //abstrakte Methode überschreiben result:=0; end; procedure TmyStrings.Insert(Index: Integer; const S: string); begin //abstrakte Methode überschreiben end; procedure TmyStrings.Clear; begin //abstrakte Methode überschreiben end; |
Re: Warum TStrings erstellen mit TStringList.Create?
Zitat:
Ok, nochmal zum Verständnis: Wenn ich eine Variable mit der Basisklasse deklariere, bleiben mir Möglichkeiten offen, die mit eine Nachfolgerklasse schon festgelegt sind. Soweit klar. Meine Fragestellung beinhaltet aber auch, dass ich von vornherein vorhabe, die Variable mit TStringList zu instanzieren. Ist das geschehen, (und das ist ja hier das Thema) kann ich die Kasse TString doch nicht mehr nutzen!? Oder meinst du vielleicht, dass man die Variable leert (TStringList.Free) und dann eine andere (Nachfolger-)Klasse instanziert? Bin ich jetzt auf dem richtigen Weg, oder liege ich jetzt ganz daneben? |
Re: Warum TStrings erstellen mit TStringList.Create?
Wie gesagt, wenn du Objekte von TStringList erzeugen/ablegen willst ist auch TStringList als Typ ok
|
Re: Warum TStrings erstellen mit TStringList.Create?
Zitat:
Wenn die Klasse als TStrings deklariert ist, hast du aber über die Variable nur direkten Zugriff auf die Anteile der TStrings-Schnittstelle. Sortieren kann man dann also nicht mehr. Handhabe es einfach so: - Variablendeklarationen so hoch wie möglich, denn dann hast du direkten Zugriff auf alle Möglichkeiten der instantitierten Klasse > also TStringList - Parameterdeklarationen so klein wie möglich, dann hast du die größte Kompatibilität zu anderen Ableitungen > also TStrings |
Re: Warum TStrings erstellen mit TStringList.Create?
Wow! Danke für die Antworten! Bitte um Geduld, das muss ich jetzt erst verdauen und testen. Melde mich dann wieder.
Guido. Edit: Gemeint sind alle Antworten ab ![]() Edit 2: Hab tatsächlich noch welche übersehen, muss also heißen: Alle Antworten ab ![]() |
Re: Warum TStrings erstellen mit TStringList.Create?
Mann oh Mann, ganz schön viel Zeugs! Ich versuche das mal möglichst kurz zusammen zu fassen. (Wird wohl trozdem ein bisschen länger :-D )
Zitat:
Zitat:
Zitat:
Hier kristallisiert sich jetzt auch eine andere Formulierung der Ausgangsfrage herraus. Denn mit zunehmenden Informationen scheint es mir immer unsinniger, eine TString-Variable mit TStringList.Create zu instanzieren. In einem Beispiel von sirius verzweigt er zwar in einer Abfrage nach TStringlist.create,
Delphi-Quellcode:
aber wirklich Sinn macht es doch nicht, da nur die Eigenschaften und Methoden von TStrings verwendet werden können. Es kann an der obigen Stelle doch mit was-weiß-ich-was instanziert werden, es bleibt doch immer nur TStrings verfügbar. Oder sehe ich das falsch?
var x:TStrings;
begin if irgendetwas=irgendetwasanders then x:=TStringlist.create // <-- hier else x:=Memo1.lines; end; Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Puh, geschafft. Vielen Dank an alle für die Antworten! :thumb: Falls ich das Resümee (schreibt man wirklich so) falsch erstellt habe, freue ich mich über Berichtigung. Falls es richtig ist (könnte fast eine if-Abfrage formulieren *smile*) freue ich mich über Bestätigung. Guido. PS: Ich hoffe, ich hab da nicht allzuviele Fehler drin, es war jetzt doch ziemlich viel aufzuarbeiten. |
Re: Warum TStrings erstellen mit TStringList.Create?
Zitat:
Zitat:
Zitat:
Delphi-Quellcode:
var
sl, sl2: TStrings; begin sl := TStrings.Create; sl2 := TStringList.Create; (sl2 as TStringList).Sort; //Funktioniert; (sl as TStringList).Sort; //Funktioniert nicht, da die Instanz die Methode nicht kennt |
Re: Warum TStrings erstellen mit TStringList.Create?
Zitat:
Damit will ich sagen, dass mir trotz der hier erklärten Möglichkeiten (die ich ja auch verstehe) nicht einleuchten will, warum man (gerade) bei TStringList-Instanzierung mit der Basisklasse deklarieren sollte. Ich sehe zwar die hier genannten Möglichkeiten, die sich dadurch ergeben, aber nicht die Notwendigkeit dieser Vorgehensweise. Anders ausgedrückt: Es macht soviel Sinn, wie den Mount Everest zu besteigen. Man kann das tun, ist vielleicht toll, muss man aber nicht. Weshalb ich von Fehler spreche ist, dass ich es einfach "richtiger" finde, eine Instanz von TStringList auch mit TStringList zu deklarieren. Spätestens nach all den Postings hier finde ich auch keinen Nachteil, der dadurch entstehen würde, und der nicht mit irgendeinem TypeCast zu beheben wäre. Zitat:
Zum Schluss sei noch erwähnt: Zitat:
Kann jemand mal in einer neueren Delphi-Version nachsehen, ob es dort auch 1:1 übernommen wurde? Es ist zu finden unter dem Thema "Eine neue Stringliste erstellen", Abschnit "Kurzlebige Stringlisten". Ansonsten: Vielen Dank für all die Postings! Guido. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:20 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