Dies wurde durch die Antwort von Deltic inspiriert, ich wollte ein Gegenbeispiel liefern, das beweist, dass Sie Generics für die Tierfütterungsroutine verwenden können. (dh: Polymorphe generische Liste)
Zunächst einige Hintergrundinformationen: Der Grund, warum Sie generische Tiere mit einer generischen Basisklassenliste füttern können, liegt darin, dass Sie normalerweise eine solche Vererbung haben:
TBaseList = Klasse
// Einige Codezeilen, um dies tatsächlich zu einer Liste zu machen
end
TSpecificList = Klasse(TBaseList)
// Code, der die Routinen Add und GetItem wieder einführt, um die TSpecificList in eine typsichere Liste eines anderen Typs zu verwandeln, die mit der TBaseList kompatibel ist
end
Dies funktioniert nicht mit Generics, weil Sie normalerweise dies haben:
TDogList = TList
end
TCatList = TList
end
... und der einzige "gemeinsame Vorfahr" für beide Listen ist TObject
- überhaupt nicht hilfreich. Aber wir können einen neuen generischen Listentyp definieren, der zwei Klassenargumente annimmt: ein TAnimal
und ein TSpecificAnimal
, um eine typsichere Liste von TSpecificAnimal
zu erstellen, die mit einer generischen Liste von TAnimal
kompatibel ist. Hier ist die grundlegende Typdefinition:
TCompatibleList = Klasse(TObjectList)
privat
function GetItem(i: Integer): T2;
public
procedure Add(A:T2);
Eigenschaft Item[i:Integer]:T2 lesen GetItem;Default;
end;
Unter Verwendung dessen können wir folgendes tun:
TAnimal = Klasse;
TDog = Klasse(TAnimal);
TCat = Klasse(TAnimal);
TDogList = TCompatibleList;
TCatList = TCompatibleList;
Auf diese Weise erben sowohl TDogList als auch TCatList tatsächlich von TObjectList
, sodass wir jetzt eine polymorphe generische Liste haben!
Hier ist eine vollständige Konsolenanwendung, die dieses Konzept in Aktion zeigt. Und diese Klasse wird jetzt in meine ClassLibrary zur zukünftigen Wiederverwendung aufgenommen!
Programm Projekt23;
{$APPTYPE CONSOLE}
Verwendet
SysUtils, Generics.Collections;
Art
TAnimal = Klasse
end;
TDog = Klasse(TAnimal)
end;
TCat = Klasse(TAnimal)
end;
TCompatibleList = Klasse(TObjectList)
privat
function GetItem(i: Integer): T2;
public
procedure Add(A:T2);
Eigenschaft Item[i:Integer]:T2 lesen GetItem;Default;
end;
{ TX }
Verfahren TCompatibleList.Add(A: T2);
begin
Geerbt Add(T1(TObject(A)));
end;
Funktion TCompatibleList.GetItem(i: Integer): T2;
begin
Ergebnis := T2(TObject(Geerbt Items[i]));
end;
Verfahren FeedTheAnimals(L: TObjectList);
var A: TAnimal;
begin
für A in L tun
SchreibeLn('Füttern einer ' + A.ClassName);
end;
var Hunde: TCompatibleList;
Katzen: TCompatibleList;
Gemischt: TObjectList;
begin
versuchen
// Füttere einige Hunde
Hunde := TCompatibleList.Erstellen;
versuchen
Hunde.Add(TDog.Erstellen);
FeedTheAnimals(Hunde);
endlich Hunde.Free;
end;
// Füttere einige Katzen
Katzen := TCompatibleList.Erstellen;
versuchen
Katzen.Add(TCat.Erstellen);
FeedTheAnimals(Katzen);
endlich Katzen.Free;
end;
// Füttere eine gemischte Gruppe
Gemischt := TObjectList.Erstellen;
versuchen
Gemischt.Add(TDog.Erstellen);
Gemischt.Add(TCat.Erstellen);
FeedTheAnimals(Gemischt);
endlich Gemischt.Free;
end;
Readln;
außer
auf E: Ausnahme tun
SchreibeLn(E.ClassName, ': ', E.Message);
end;
end.