Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Ersetzen der privaten class procedure QuickSort<T> (. . .) der Klasse TArray (https://www.delphipraxis.net/188407-ersetzen-der-privaten-class-procedure-quicksort-t-der-klasse-tarray.html)

Andreas13 29. Feb 2016 14:55

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:
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 &#8222;neuen Routine&#8220; zunächst Delphi XE5&#8217;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.
Hierzu verwendete ich einen kleinen 4-Zeiler aus dem Buch: Rolliston, Ch.: Delphi XE2 Foundations: (2012) Seite 288.

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

Uwe Raabe 29. Feb 2016 16:09

AW: Ersetzen der privaten class procedure QuickSort<T> (. . .) der Klasse TArray
 
Delphi-Quellcode:
TArray
ist etwas völlig anderes als
Delphi-Quellcode:
TArray<T>
. Schau dir mal die beiden Deklarationen an und überleg mal, warum du keine Variable vom Typ MyTArray<T> brauchst.

Andreas13 29. Feb 2016 16:35

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

Stevie 29. Feb 2016 16:36

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.

Uwe Raabe 29. Feb 2016 16:59

AW: Ersetzen der privaten class procedure QuickSort<T> (. . .) der Klasse TArray
 
Zitat:

Zitat von Andreas13 (Beitrag 1331707)
Könntest Du mir bitte den Unterschied zwischen TArray und TArray<T> erklären?

Delphi-Quellcode:
TArray<T> = array of T

TArray = class
Delphi-Quellcode:
TArray
ist eine Hilfsklasse, die eine Reihe generischer Methoden zur Verfügung stellt. Insbesondere speichert
Delphi-Quellcode:
TArray
keine Daten irgendwelchen Typs.

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?

Andreas13 29. Feb 2016 18:28

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

Uwe Raabe 29. Feb 2016 18:40

AW: Ersetzen der privaten class procedure QuickSort<T> (. . .) der Klasse TArray
 
Delphi-Quellcode:
TArray.Sort<T>
arbeitet doch schon mit Arrays beliebigen Typs.

Delphi-Quellcode:
var
  intarr: TArray<Integer>;
  strArr: TArray<string>;
begin
  TArray.Sort<Integer>(intArr);
  TArray.Sort<string>(strArr);
end;

Der schöne Günther 29. Feb 2016 19:00

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. Siehe Doku

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.

Andreas13 29. Feb 2016 22:08

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:
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.
Herzlichen Dank an Euch Alle!

Gruß, Andreas

Phoenix 1. Mär 2016 11:53

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 11:07 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz