Article View: pl.comp.lang.delphi
Article #334825Re: E2032 For loop control variable must have ordinal type
From: jh
Date: Tue, 17 Jan 2012 09:45
Date: Tue, 17 Jan 2012 09:45
115 lines
5547 bytes
5547 bytes
W dniu 16.01.2012 23:57, wloochacz pisze:
> A tak:
> sl := TSingleList.(TSingleList.CreateList('Single List', -1));
> I dlaczego się kompiluje?
> No więc właśnie...
OK (wiadomo, bez kropki przed nawiasem). Tylko trochę to pokrętne, bo:
type
TCustomList<T> = class(TObjectDictionary<Integer, T>)
private
FListID: Integer;
FListName: string;
public
class function CreateList(const AListName: String;
const AListID: Integer = -1): TCustomList<T>;
property ListName: string read FListName write FListName;
property ListID: Integer read FListID write FListID;
end;
TSingleList = class(TCustomList<string>)
public
end;
var
sl: TSingleList;
s: string;
sl := TSingleList(TSingleList.CreateList('Single List', -1));
try
if (sl is TCustomList<string>) then
s := 'sl IS TCustomList<string>, '
else
s := 'sl IS NOT TCustomList<string>, ';
if (sl is TSingleList) then
s := s + 'and IS TSingleList, its ClassName is ' + sl.ClassName
else
s := s + 'and IS NOT TSingleList, its ClassName is ' + sl.ClassName;
finally
sl.Free;
end;
s zwraca:
sl IS TCustomList<string>, and IS TSingleList, its ClassName is
TCustomList<System.string>
Same generyki w wersji Delphi zrozumiałem tak:
Kod - zapis - jest w momencie kompilacji generowany na podstawie
szablonu, po podstawieniu w miejsce placeholderów właściwych typów.
Czyli, kompilator dostaje już kod na zasadzie search&replace <T> na
<nazwa typu>. Jeżeli teraz posługuję się dziedziczeniem takiej
generycznej definicji, to zrozumiałem to tak, że (obrazowo) mam kolejne
wersje kodu z dopisaną funkcjonalnością, które już (podając konkretny
typ) same dokonują owego search&replace, wprowadzają nowe placeholdery i
finalnie kompilator dostaje taki scalony kod klasy, która z nazwami tych
nadrzędnych generycznych klas nie ma nic wspólnego. Zatem w moim
przykładzie TCustomList<string> jest zupełnie inną klasą niż
TSingleList, choć powstały na bazie tego samego zapisu.
[Po 5 minutach :D]
Przeczytałem powyższe i chyba zrozumiałem, gdzie popełniam błąd. Powinno
być tak, że oprócz tej mojej docelowej klasy (TSingleList) powstają
również TCustomList<string>, TObjectDictionary<Integer, string>,
TDictionary<Integer, String> itd. Czyli na podstawie podawanych
konkretnych typów - podczas dziedziczenia, również tworzony są klasy
nadrzędne z tymi właśnie typami. Zatem powstaje nie tyle finalna -
"scalona" wersja klasy, ale te klasy nadrzędne - podobnie jak to ma
miejsce w tradycyjnym dziedziczeniu. Takie "na chłopski rozum"
tłumaczenie, chyba jest sensowne w kontekście powyższej wartości owego
"s". Tam konstruktor był w TCustomList<T> i stąd zwrócona taka nazwa
klasy obiektu TSingleList, choć posiada on metody i pola dostępne
dopiero od klasy TSingleList, a które nie zostały jeszcze wprowadzone w
TCustomList<T>.
> Nie wiem dlaczego, ale próbujesz na siłę wykorzystać typy generyczne aby
> robiły za polimorfizm.
> Po co tak?
To tylko w ramach nauki. Dotąd robiłem tradycyjnie, bez typów
generycznych. Liczyłem na pominięcie tego rzutowania, które miałem w
listach zbudowanych z np. TObjectList czy TList.
> To co chcesz uzyskać, to się da i robi, tyle że bez typów generycznych
> za to z typami klasowymi.
> Zerknij np. na to:
> http://docwiki.embarcadero.com/Libraries/en/Vcl.ComCtrls.TCustomTreeView.OnCreateNodeClass
>
> Jak widzisz w tym zdarzeniu możesz do TTreeView przekazać dowolną klasę
> (która dziedziczy z TTreeNode) aby Node (liść, węzeł), który zostanie
> utworzony był instancją klasy którą przekażesz w tym zdarzeniu.
OK, to jest zrozumiałe. Tylko zamotałem się z tym dziedziczeniem
generyków. To powyższe (OnCreateNodeClass) można nazwać fabryką klas
dziedziczących z TTreeNode?
> Spójrz jak rozwiązano np. sortowanie w TList<T> (aczkolwiek to nieco
> zakręcony przykład) ale co ważniejsze, dlaczego sam algorytm sortowania
> został oddelegowany na zewnątrz i nie jest w żaden sposób
> zaimplementowany w TList<T>?
> Jakbyś zaimplementował sortowanie elementów listy dla ogólnego typu
> (czyli <T>), bo przecież na pewni nie wewnątrz klasy TList<T>, prawda?
No właśnie dotarłem w lekturze do metod anonimowych i jest mowa o
sortowaniu TList<T> :P
Dzięki za wskazówki.
jh
Technical Details
Message-ID:
<jf3g0d$iq1$1@inews.gazeta.pl>Path:
mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.gazeta.pl!not-for-mailReferences:
<jf1eso$r2g$1@inews.gazeta.pl> <jf1hvq$6dj$1@inews.gazeta.pl> <15e8um5ehdue7.dlg@hell.heaven> <jf27m9$is9$1@inews.gazeta.pl> <jf2a0j$qcl$1@inews.gazeta.pl>Show Full Headers
Complete Article Headers
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.gazeta.pl!not-for-mail From: jh <no-email@sorry.com> Newsgroups: pl.comp.lang.delphi Subject: Re: E2032 For loop control variable must have ordinal type Date: Tue, 17 Jan 2012 10:45:49 +0100 Organization: "Portal Gazeta.pl -> http://www.gazeta.pl" Lines: 116 Message-ID: <jf3g0d$iq1$1@inews.gazeta.pl> References: <jf1eso$r2g$1@inews.gazeta.pl> <jf1hvq$6dj$1@inews.gazeta.pl> <15e8um5ehdue7.dlg@hell.heaven> <jf27m9$is9$1@inews.gazeta.pl> <jf2a0j$qcl$1@inews.gazeta.pl> NNTP-Posting-Host: rk-193-19-124-170.kielce.net.pl Mime-Version: 1.0 X-Trace: inews.gazeta.pl 1326793551 19265 193.19.124.170 (17 Jan 2012 09:45:51 GMT) X-Complaints-To: usenet@agora.pl NNTP-Posting-Date: Tue, 17 Jan 2012 09:45:51 +0000 (UTC) X-User: jh0909nowe In-Reply-To: <jf2a0j$qcl$1@inews.gazeta.pl> User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:9.0) Gecko/20111222 Thunderbird/9.0.1 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit