Das liegt daran, dass die Eigenschaft Items deiner TPenalties-Klasse (worauf du mit dem []-Operator implizit zugreifst) von TObjectList geerbt ist. TObjectList wurde so konzipiert, dass es Objekte aller Arten speichern kann, deshalb wurde bei der Deklaration der "Urahn" aller Klassen unter Delphi, TObject, gewählt. Da du aber wie gesagt jedes erdenkliche Objekt in dieser Liste speichern kannst, beschwert sich Delphi: Denn es könnte ja etwas völlig anderes als eine TPenalty-Instanz dort gespeichert sein, und das gäbe dann einen Fehler.
Du hast zwei Möglichkeiten: Entweder du machst einen Typecast auf TPenalty, oder du überschreibst gleich in TPenalties die Items-Property. Das geht etwa so:
Delphi-Quellcode:
TPenalties = class(TObjectList)
private
function GetItem(Index: integer): TPenalty;
procedure SetItem(Index: integer; AItem: TPenalty);
public
// Siehe dazu die Online-Hilfe zum Stichwort Properties...
property Items[Index: integer]: TPenalty read GetItem write SetItem; default;
end;
function TPenalties.GetItem(Index: integer): TPenalty;
begin
// per inherited wird der gleichnamige Getter von TObjectList aufgerufen,
// das Ergebnis wird nach TPenalty gecastet
Result := TPenalty(inherited GetItem(Index));
end;
procedure TPenalties.SetItem(Index: integer; AItem: TPenalty);
begin
// Hier ist kein Typecast nötig, weil TObject der "Urahn" von allen Klassen
// und somit auch TPenalty ist, daher also alle Klassen zu den Schnittstellen von
// TObject kompatibel sind.
inherited SetItem(Index, AItem);
end;
Natürlich ist es sinnvoll, in dem Zug auch gleich die Methoden Add, Remove etc zu überschreiben, sodass diese ebenfalls typensicher sind, sprich als Parameter TPenalty statt TObject entgegen nehmen. So sicherst du die Klasse auch gegen Bedienfehler von außen ab, denn solange der Nutzer der Klasse es nicht gerade mit Typecasts darauf anlegt, Fehler zu provozieren, schmeißt der Compiler beim Kompilieren jedes mal einen Fehler und bricht den Kompiliervorgang ab, wenn irgendwo ein falsches Objekt zugewiesen wird.