![]() |
Delphi-Version: XE5
Ersetzen der privaten class procedure QuickSort<T> (. . .) der Klasse TArray
Liste der Anhänge anzeigen (Anzahl: 2)
Hallo Delphi-Community,
ich möchte die „mitgelieferte“ Sortierroutine QuickSort der Klasse TArray in System.Generics.Collections durch eine verbesserte QuickSort-Routine ersetzen. Hierzu habe ich eine Klasse von TArray wie folgt abgeleitet:
Delphi-Quellcode:
Hierzu verwendete ich einen kleinen 4-Zeiler aus dem Buch: Rolliston, Ch.: Delphi XE2 Foundations: (2012) Seite 288.
unit Test_TArray_QuickSort;
{$R-,T-,X+,H+,B-} // genauso, wie in unit System.Generics.Collections interface uses System.Generics.Collections , System.Generics.Defaults ; type MyTArray = class(TArray) private class procedure QuickSort<T>(var Values: array of T; const Comparer: IComparer<T>; L, R: Integer); end; implementation class procedure MyTArray.QuickSort<T>(var Values: array of T; const Comparer: IComparer<T>; L, R: Integer); Begin // hier neue QuickSort-Routine End; Für Testzwecke habe ich in der beiliegenden Unit anstelle der „neuen Routine“ zunächst Delphi XE5’s Originalversion unverändert übernommen. Im folgenden Konsolen-Programm wollte ich die neue Klasse austesten: program Sortieren_0; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils , System.Generics.Collections , Test_TArray_QuickSort in 'Test_TArray_QuickSort.pas'; VAR S : String; Arr : TArray<String>; MyArr: MyTArray<String>; // hier rebelliert der XE5-Compiler! Warum????????? Begin Try // Code nach: Rolliston, Ch.: Delphi XE2 Foundations: (2012) Seite 288: Arr:= TArray.Create<String>('things', 'SOME', 'some', 'THINGS'); TArray.Sort<String>(Arr); For S in Arr Do Write(S, ' '); WriteLn; MyArr:= MyTArray.Create<String>('things', 'SOME', 'some', 'THINGS'); MyTArray.Sort<String>(MyArr); For S in MyArr Do Write(S, ' '); WriteLn; ReadLn; Except on E: Exception do Writeln(E.ClassName, ': ', E.Message); End; End. Der Test funktioniert einwandfrei mit dem Objekt der Original-Klasse TArray, das Programm lässt sich jedoch bei der absolut identischen Vorgehensweise mit der Instanz der abgeleiteten Klasse MyTArray NICHT einmal compilieren. Anscheinend gilt doch die lateinische Weisheit „Quod licet Iovi, non licet bovi“. Ich bin kurz vor dem Verzweifeln…:( Im Anhang sind beide komplette Files dabei: Program Sortieren_0.dpr und unit Test_TArray_QuickSort.pas dabei. Könnte mir jemand von den Object-Profis freundlicherweise helfen? Vielen Dank im Voraus! Gruß Andreas |
AW: Ersetzen der privaten class procedure QuickSort<T> (. . .) der Klasse TArray
Delphi-Quellcode:
ist etwas völlig anderes als
TArray
Delphi-Quellcode:
. Schau dir mal die beiden Deklarationen an und überleg mal, warum du keine Variable vom Typ MyTArray<T> brauchst.
TArray<T>
|
AW: Ersetzen der privaten class procedure QuickSort<T> (. . .) der Klasse TArray
Sorry Uwe, aber ich komme als "Object-Anfänger" leider nicht dahinter.
Könntest Du mir bitte den Unterschied zwischen TArray und TArray<T> erklären? Ich dachte <T> signalisiert dem Compiler, dass der übergebene Typ "vererbt" wird. Danke! Andreas |
AW: Ersetzen der privaten class procedure QuickSort<T> (. . .) der Klasse TArray
Dein Ansatz wird nicht funktionieren. Denn TArray.Sort wird immernoch TArray.QuickSort aufrufen und nicht plötzlich MyTArray.QuickSort.
Vorrausgesetzt du willst diese Funktionalität auch in TList<T>.Sort und so verwenden, wird das auch nicht hinhauen, denn du bekommst dort ohne Änderung der RTL Sourcen keinen andere Implementierung untergeschoben. |
AW: Ersetzen der privaten class procedure QuickSort<T> (. . .) der Klasse TArray
Zitat:
Delphi-Quellcode:
TArray<T> = array of T
TArray = class
Delphi-Quellcode:
ist eine Hilfsklasse, die eine Reihe generischer Methoden zur Verfügung stellt. Insbesondere speichert
TArray
Delphi-Quellcode:
keine Daten irgendwelchen Typs.
TArray
Wie Stevie schon sagte, ist dein ganzes Bemühen sinnlos, da QuickSort nicht virtuell ist und somit nicht überschrieben werden kann. Du kannst allenfalls eine Kopie von TArray nehmen und dort deine Implementierung von QuickSort unterbringen. Das hat aber auf die interne Implementation und deren Verwendung keinen Einfluss. Vielleicht erklärst du mal, was du eigentlich erreichen willst? |
AW: Ersetzen der privaten class procedure QuickSort<T> (. . .) der Klasse TArray
danke Uwe und Stefan für die Aufklärung und die Erklärung des Unterschiedes zwischen den beiden Typen.
Mein ursprüngliches Ziel war es, anstelle meiner x typ-spezifischen Sortierroutinen EINE einzige Routine zu verwenden, die ALLE Array-Typen "schluckt". Dazu hat mich TArray.QuickSort<T> inspiriert. Als ersten Schritt wollte ich dazu als "schnelle" Lösung ein abgeleitetes Objekt a la oben aufgeführten Quellcode benutzen. Denn auch ich habe bemerkt, dass TArray.QuickSort<T> intern auf eine ziemlich komplexe Weise mit aller Welt verknüpft ist. Als zweiten Schritt wollte ich schließlich ein eigenes typ-unabhängiges Objekt erstellen... Lässt sich mit objektorientiertem Ansatz eine solche Routine - ohne Pointer-Akrobatik - programmieren, die ALLE Array-Inhalte verarbeiten kann? Bisher habe ich - prozedural - meistens mit "overload" gearbeitet. Gruß, Andreas |
AW: Ersetzen der privaten class procedure QuickSort<T> (. . .) der Klasse TArray
Delphi-Quellcode:
arbeitet doch schon mit Arrays beliebigen Typs.
TArray.Sort<T>
Delphi-Quellcode:
var
intarr: TArray<Integer>; strArr: TArray<string>; begin TArray.Sort<Integer>(intArr); TArray.Sort<string>(strArr); end; |
AW: Ersetzen der privaten class procedure QuickSort<T> (. . .) der Klasse TArray
Wenn du beispielsweise ein Array von Records oder sonstwas sortieren willst kannst du bei TArray.Sort auch einen IComparer<T> angeben.
![]() Sieht dann, etwas länglich, so aus:
Delphi-Quellcode:
program Project11;
{$APPTYPE CONSOLE} {$R *.res} uses System.Generics.Collections, System.Generics.Defaults; type TMyRecord = record alsWort: String; alsZahl: Integer; end; var a, b, c: TMyRecord; comparer: IComparer<TMyRecord>; meinArray: TArray<TMyRecord>; begin a.alsWort := 'Dreiundzwanzsch'; a.alsZahl := 23; b.alsWort := 'Nüscht'; b.alsZahl := 0; c.alsWort := 'Sievenunfünfzsch'; c.alsZahl := 57; comparer := TComparer<TMyRecord>.Construct( function(const left, right: TMyRecord): Integer begin Result := TComparer<Integer>.Default.Compare(left.alsZahl, right.alsZahl); end ); SetLength(meinArray, 3); meinArray[0] := a; meinArray[1] := b; meinArray[2] := c; // Ab XE7 ginge stattdessen auch das hier: //meinArray := [a, b, c]; TArray.Sort<TMyRecord>(meinArray, comparer); WriteLn(meinArray[0].alsWort); WriteLn(meinArray[1].alsWort); WriteLn(meinArray[2].alsWort); ReadLn; end. |
AW: Ersetzen der privaten class procedure QuickSort<T> (. . .) der Klasse TArray
Hallo zusammen,
danke für die vielen nützlichen Tipps, Hinweise und Anregungen: ich habe dabei von EUCH eine ganze Menge gelernt und Vieles ist mir klar geworden! Mit diesem soeben erworbenen Know-how konnte ich sogar meine ursprüngliche Routine realisieren und TArray.QuickSort(. . .) in den ABGELEITETEN Klassen auf „meine“ Sortierroutine umbiegen. Hier ist das Ergebnis, falls sich jemand dafür interessieren sollte:
Delphi-Quellcode:
Herzlichen Dank an Euch Alle!
unit Test_TArray_QuickSort;
interface uses System.Generics.Collections , System.Generics.Defaults ; type MyTArray = class(TArray) private class procedure QuickSort<T>(var Values: array of T; const Comparer: IComparer<T>; L, R: Integer); public class procedure Sort<T>(var Values: array of T); // !! end; implementation class procedure MyTArray.QuickSort<T>(var Values: array of T; const Comparer: IComparer<T>; L, R: Integer); Begin // hier soll die neue QuickSort-Routine folgen: End; class procedure MyTArray.Sort<T>(var Values: array of T); begin QuickSort<T>(Values, TComparer<T>.Default, Low(Values), High(Values)); end; Und das Testprogramm: program Sortieren_0_verbessert; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils , System.Generics.Collections , Test_TArray_QuickSort in 'Test_TArray_QuickSort.pas'; VAR S : String; MyArr: TArray<String>; // !!! Begin MyArr:= TArray<String>.Create('things', 'SOME', 'some', 'THINGS'); SetLength(MyArr, 5); MyArr[4]:='Irgend etwas'; MyTArray.Sort<String>(MyArr); For S in MyArr Do Write(S, ' '); WriteLn; ReadLn; End. Gruß, Andreas |
AW: Ersetzen der privaten class procedure QuickSort<T> (. . .) der Klasse TArray
Andreas, bitte achte in Zukunft darauf in Deinen Posts den Quellcode mit [delphi]-tags zu umschliessen, damit dieser auch richtig formatiert wird.
Das habe ich jetzt gemacht, weil es Beschwerden von Usern gab die das schlecht lesen konnten, aber für die Zukunft bitte selber daran denken, ja? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:48 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