Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi TStringlist sortieren (https://www.delphipraxis.net/84134-tstringlist-sortieren.html)

little_budda 11. Jan 2007 20:38


TStringlist sortieren
 
Hallo,

ich habe mir eine Stringliste deklariert mit folgendem Code
Delphi-Quellcode:
...
  slOutList : tstrings;
...
  slOutList := tstringlist.create();
...
Nun sind ca 400 Einträge in der Liste und ich würde sie gern alphabetisch sortieren.
Hier im Forum finde ich jede Menge Beispiele mit ".sort"
Nur wenn ich folgen Code probiere
Delphi-Quellcode:
...
  slOutList.sort;
...
sagt mir mein Compiler immer "Undefinierter Bezeichner 'sort'

Wo bitte liegt mein Fehler?

Gruß Holger.

:gruebel:

Bernhard Geyer 11. Jan 2007 20:43

Re: TStringlist sortieren
 
Sort gibt nur bei TStringList und nicht bei TStrings.
Und da deine Variable vom Typ TStrings ist ...

mkinzler 11. Jan 2007 20:50

Re: TStringlist sortieren
 
Zitat:

Zitat von Bernhard Geyer
Sort gibt nur bei TStringList und nicht bei TStrings.
Und da deine Variable vom Typ TStrings ist ...

???
Das dürfte doch kein Problem sein, da TStringList ja ne implementierende Abelitung der abstrakten Klasse TStrings ist.

Man muß nur Casten:


Delphi-Quellcode:
(slOutList as TStringList).sort;

little_budda 11. Jan 2007 21:03

Re: TStringlist sortieren
 
Danke.

Mit "slOutList as TStringList" klappt es

Gruß Holger.

Bernhard Geyer 11. Jan 2007 21:23

Re: TStringlist sortieren
 
Zitat:

Zitat von mkinzler
Zitat:

Zitat von Bernhard Geyer
Sort gibt nur bei TStringList und nicht bei TStrings.
Und da deine Variable vom Typ TStrings ist ...

???
Das dürfte doch kein Problem sein, da TStringList ja ne implementierende Abelitung der abstrakten Klasse TStrings ist.

Man muß nur Casten:


Delphi-Quellcode:
(slOutList as TStringList).sort;

Stimmt schon. Wenn schon 'ne lokale Variable dann gleich den passenden Typ nehmen. Sonst casted man blindlinks: Ah TStrings hab ich: Caste ich mal schnell nach TStringlist und schon paßt es.

3_of_8 11. Jan 2007 21:26

Re: TStringlist sortieren
 
Wieso überhaupt TStrings deklarieren und nicht TStringList? Die Abstraktion braucht man in dem Fall ja extrem selten.

marabu 12. Jan 2007 08:06

Re: TStringlist sortieren
 
Hallo Manuel,

Zitat:

Zitat von 3_of_8
Wieso überhaupt TStrings deklarieren und nicht TStringList?

Informatiker lernen, dass man Variablen stets nur für diejenige Superklasse vereinbart, deren Methoden und Eigenschaften man zu nutzen gedenkt. Es handelt sich dabei um eine Spielart von information hiding. Dieses universelle Grundprinzip kennen nicht nur Software Ingenieure ...

Grüße vom marabu

Union 12. Jan 2007 08:42

Re: TStringlist sortieren
 
In diesem Fall (nämlich wenn man eine in der Superklasse nicht deklarierte Methode verwenden will, e.g. sort) hat man sich aber dann elegant vor sich selbst versteckt. Wenn man weiss was man will, sollte man natürlich so arbeiten, u.a. bei Streams.

bernau 12. Jan 2007 09:29

Re: TStringlist sortieren
 
Zitat:

Zitat von marabu
Zitat:

Zitat von 3_of_8
Wieso überhaupt TStrings deklarieren und nicht TStringList?

Informatiker lernen, dass man Variablen stets nur für diejenige Superklasse vereinbart, deren Methoden und Eigenschaften man zu nutzen gedenkt. Es handelt sich dabei um eine Spielart von information hiding. Dieses universelle Grundprinzip kennen nicht nur Software Ingenieure ...

Ist für mich nicht logisch. (Liegt vieleicht daran, daß ich kein studierter Informatiker bin, sondern nur ein autodidaktischer Programmierer :-)

Ich denke, wenn ich in einer Procedure ein Object deklariere, dann verwende ich als Variable auch den Type den ich brauche. Un anscheinend gedenkt little_budda ja die Functionen von TStringlist zu verwenden. Warum dann nicht die Variable als TStringlist deklarieren?


Gerd

marabu 12. Jan 2007 09:53

Re: TStringlist sortieren
 
Hallo Gerd,

die eigentliche Frage hatte Bernhard schon in Beitrag #2 beantwortet. Mein Beitrag bezog sich auf die Frage von Manuel:

Zitat:

Zitat von 3_of_8
Wieso überhaupt TStrings deklarieren und nicht TStringList? Die Abstraktion braucht man in dem Fall ja extrem selten.

Durch den hervorgehoben Nachsatz habe ich die Frage als allgemeine Frage angesehen und versucht eine allgemeine Antwort zu geben.

Meine Antwort möchte ich so verstanden wissen:

Wird eine StringList instanziert, dann verwende ich eine Objektvariable vom Typ TStrings, wenn ich sowieso nur die von TStrings bereit gestellten Methoden verwenden möchte. Da Holger im konkreten Fall die Methode Sort() verwenden möchte, ist es kein Verstoß gegen das Universalprinzip die Objektvariable als TStringList zu deklarieren. Nur die unmotivierte Deklaration als TStringList ist unprofessionell.

Ich fürchte nach genauem Lesen, dass auch Union meinen Beitrag falsch interpretiert haben könnte und hoffe mit dieser Lesehilfe auf mehr Verständnis.

Freundliche Grüße

Bernhard Geyer 12. Jan 2007 09:54

Re: TStringlist sortieren
 
Zitat:

Zitat von marabu
Informatiker lernen, dass man Variablen stets nur für diejenige Superklasse vereinbart, deren Methoden und Eigenschaften man zu nutzen gedenkt. Es handelt sich dabei um eine Spielart von information hiding. Dieses universelle Grundprinzip kennen nicht nur Software Ingenieure ...

Für viele Fälle mag ich dir zustimmen. Aber in diesem konkreten Fall wäre dies nur sinnvoll wenn es u.U. eine globale oder Membervariable wäre und die TStrings-Klasse eine abstrakte Methode Sort hätte.

Der_Unwissende 12. Jan 2007 09:55

Re: TStringlist sortieren
 
Zitat:

Zitat von bernau
Ich denke, wenn ich in einer Procedure ein Object deklariere, dann verwende ich als Variable auch den Type den ich brauche. Un anscheinend gedenkt little_budda ja die Functionen von TStringlist zu verwenden. Warum dann nicht die Variable als TStringlist deklarieren?

Hi,
dass ganze solltest Du nicht nur auf dieses Beispiel beziehen (hier wird schließlich die Methode sort benötigt und eine entsprechende Superklasse, eben TStringlist, sollte vereinbart werden).
Aber im Allgemeinen verwendet man gerne abstrakte Klassen / Interfaces (als Superklasse), da man hier leicht die Implementierung austauschen kann. Typisches Beispiel wäre hier TStrings oder auch TStream. Beides abstrakte Klassen, es sind nur die Methodensignaturen sichtbar, die Implementierung existiert nur in den Nachkommen.
Wenn Du jetzt einen Stream benötigst, dann weißt Du, dass der eine Methode zum Lesen und Schreiben hat, wie aber genau die Funktionieren (ob aus einer Datei, einem Stream, einem String, ... gelesen wird ist für dich transparent). Nimm jetzt z.B. ein Kompressions-Bibliothek, die komprimiert einfach einen Stream. Was muss die dafür wissen? Na ja, wie sie die Daten aus dem Stream bekommt, was mit der Lese-Methode schon erfüllt ist. An eine Methode, die hier also nur einen Stream erwartet kannst Du jetzt sowohl Instanzen von TMemoryStream, TFileStream, THandleStream, ... (auch eigene Nachkommen) übergeben, wichtig ist eben nur, dass die die abstrakten Methoden von TStream implementieren.
Jetzt kannst Du aber auch gleich die Kompression abstrakt aufbauen, indem du einfach eine abstrakte Basis erstellst, die ein TStream Objekt bekommt und komprimiert. Hier kann dann wiederum für jeden Kompressionsalgorithmus ein eigener Nachfahre geschaffen werden, nach aussen verhalten die sich aber alle gleich.

Baust Du also so dein Programm zusammen, hast Du den Vorteil, dass die Implementierung an jeder Stelle immer leicht ausgetauscht werden kann, ohne dass sich etwas an der Programmlogik ändert.
Jetzt kann man natürlich argumentieren, dass man aber auch selten die Implementierung ändert, doch das stimmt i.d.R. nicht. Neben Fehlerkorrekturen oder Verbesserungen der Performance (z.B. TStringList durch THashedStringList ersetzen, beschleunigt das Suchen) oder anderen Verhaltens sollte man hier unbedingt die Teamarbeit betrachten. Große Projekte können natürlich nicht von nur einer Person bearbeitet werden. Typischer Weise wird man also das Gesamtproblem in kleinere Teile zerlegen, die dann von unterschiedlichen Teams/Personen gelöst werden können. Jetzt gibt es aber zwei wichtige Probleme, einerseits müssen die Teillösungen irgendwann zusammengefügt werden, anderseits bestehen aber auch häufig Abhängigkeiten. Z.B. wenn man eine Datei laden/speichern können soll, so muss bekannt sein, wie ein Datum im Speicher liegt. Hier ist es also wichtig, dass nicht jedes Team/jede Person eine eigene Vorstellung hat (und man erst beim Zusammensetzen merkt, dass die nicht kompatibel sind).
Natürlich kann man warten, bis alle Abhängigkeiten aufgelöst sind, bevor man ein Problem löst, dann würde es aber im schlimmsten Fall dazu kommen, dass auch eine Person alles machen kann (keine Parallelen Arbeiten möglich). Beim Parallelen Arbeiten hat man dann wiederum das Problem, dass einige Probleme schneller gelöst werden können als andere. Jede Menge Probleme.
Die können aber alle mit der Verwendung von abstrakten Datentypen erschlagen werden. Legt man verbindliche Schnittstellen (eben nur die Signatur der öffentlichen Methoden) fest, so muss jede Implementierung diese erfüllen. Jede Gruppe kann sich dann auf diese Schnittstellen beziehen, ohne wirklich zu wissen wie und wann die eigentliche Implementierung der externen (nicht zur Gruppe gehörigen) Datentypen erfolgt.

Viele der Vorteile kann man auch gleich bei Delphi bewundern, z.B. die Möglichkeit, dass ein TImage-Objekt alle TPicture-Nachkommen anzeigen kann, ohne dass diese schon bekannt waren, also TImage geschrieben wurde. Schreibt z.B. jmd. einen TPicture-Nachfahren für Tiff-Files, so könnte man diese einfach in einem TImage anzeigen, da hier eine der abstrakten Methoden für das Zeichnen auf einen Canvas zuständig ist, der halt übergeben wird. Auch beim Drucken sieht es ähnlich aus, es wird einfach nur auf einen Canvas gezeichnet, ob es nun der Canvas eines Druckers, einer Bitmap oder von sonst was ist bleibt völlig transparent (für Methoden wie BitBlt)

Gruß Der Unwissende

marabu 12. Jan 2007 09:57

Re: TStringlist sortieren
 
Hallo Bernhard,

deinen Beitrag #11 hast du bestimmt geschrieben ohne meinen Beitrag #10 gelesen zu haben - oder?

Freundliche Grüße

marabu 12. Jan 2007 10:02

Re: TStringlist sortieren
 
Jetzt trifft mich der Schlag - 601 Wörter in 26 Minuten. Danke für diese umfassende und zielgruppengerechte Darstellung, (Un)Wissender.

Freundliche Grüße

Udontknow 12. Jan 2007 10:04

Re: TStringlist sortieren
 
*BITTE LOESCHEN*

Bernhard Geyer 12. Jan 2007 10:16

Re: TStringlist sortieren
 
Zitat:

Zitat von marabu
deinen Beitrag #11 hast du bestimmt geschrieben ohne meinen Beitrag #10 gelesen zu haben - oder?

Genau. #10 hatte ich nicht gelesen.

Der_Unwissende 12. Jan 2007 10:19

Re: TStringlist sortieren
 
Zitat:

Zitat von marabu
Jetzt trifft mich der Schlag - 601 Wörter in 26 Minuten. Danke für diese umfassende und zielgruppengerechte Darstellung, (Un)Wissender.

Danke eher Dir, dass Du das Thema angesprochen hast!

Gruß Der (weiterhin) Unwissende

bernau 12. Jan 2007 11:08

Re: TStringlist sortieren
 
@Der_Unwissende
Das war ausführlich!!! Danke.

@Marabu
Danke für deine Klarstellung



So ist mir das schon klar. Und in vielen Punkten stimme ich mit euch überein.

Vieleicht war das Beispiel des Eingangspost das Irreführende.



Für mich hatte es so ausgesehen, daß der Programmcode von little_budda in einer Procedure vorkommt.

Delphi-Quellcode:
Procedure EineProcedure;
var
  slOutList : tstrings;
begin
  slOutList := tstringlist.create();
  // Hier wird irgendwas gemacht
  slOutList.free;
end;
Dies wäre für mich nicht sinnvoll. Dort würde ich auf Jeden Fall "slOutList : tstringlist;" deklarieren.

Was anderes ist es, wenn ich eine Stringliste in einer Function als Parameter verwenden möchte. Dort verwende ich natürlich die niedrigst mögliche Klasse.

Delphi-Quellcode:
Procedure EineProcedure(aStrings:TStrings);
begin
  // Hier wird irgendwas mit aStrings gemacht
end;
Der Function kann ich so alle Objekte übergeben, die von TStrings abgeleitet wurden. DAs macht sinn.

Es macht auch sinn z.B. TStrings statt Tstringlist als Property in einer einer Klasse zu definieren, um der Klasse ein Objekt zu übergeben, welches von TStrings abgeleitet ist um mit diesen Daten weiterzuarbeiten. Aber dann wird es in der Klasse nicht schon instanziert, wie es das Beispiel von little_budda sugeriert.

So ähnlich ist es ja auch bei TImage/TPicture. Dort wird das Bitmap,Image,Metafile,etc auch nicht im constructor von TPicture instanziert, sondern erst beim Zugriff auf das Property Picture.



Gerd


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