Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

generyki - o co chodzi

390 views
Skip to first unread message

neuron

unread,
Sep 10, 2010, 6:11:43 AM9/10/10
to
witam
moze mi ktos tak lopatologicznie wytlumaczyc o co chodzi z tymi calymi
typami generycznymi?
grzebie po googlach ale mam problemy zeby zatrybic (tak jak mialem problemy
z obiektowoscia przy przechodzeniu z TP na delphi) nie tyle co to jet a po
co to jest.

Z tego co mi sie udalo doczytac a wiekszosc materalow polsko jezycznych
(angielski znam tak slabo ze jak nie wiem o czym czytam to nic nie rozumiem)
tyczy sie dotnetu i visuala
a google na temat typy generyczne + delphi wyrzuca ino pochwaly d2010 dXE ze
tez ma ;)
doczytalem sie wiec ze typy generycnze to taka tablica (lista) gdzie mzona
wepchnac wszstko (wszytskie typy od byte do okiektow i klas) tyle ze nie
kumam po co
Tak sobie kombinuje ze moze chodzi o to aby jedna czesc programu
przekazywala innej czesci (lub innemu programowi w ramach autoamtyzacji) nie
tylko dane ale tez instrukcje co z tymi danymi zrobic.
czyli takie varianty z mozliwoscia przypisania klasy czy procedury.
Zreszta z variantami tak naprawde zatrybilem o co chodzi gdy zobaczylem jak
program przekazuje parametry do FastReporta i teraz tak sobie kombinuje ze
moze za pomoca generykow do takiego fast reporta
mozna by przekazac nie tylko wartosci zmiennych do wyswietlenia ale tez
informacje (klase dla skryptu, formule dla pola wyliczenwego) jak obrobic
dane w innych polach wydruku. Ale moze bredze ;)

wojtek


PaSkol

unread,
Sep 10, 2010, 6:37:18 AM9/10/10
to
W dniu 2010-09-10 12:11, neuron pisze:

> moze mi ktos tak lopatologicznie wytlumaczyc o co chodzi z tymi calymi
> typami generycznymi?
> grzebie po googlach ale mam problemy zeby zatrybic (tak jak mialem problemy
> z obiektowoscia przy przechodzeniu z TP na delphi) nie tyle co to jet a po
> co to jest.

A to czytałeś? Do C#, ale z pierwszej strony można już sobie jakieś
intuicje o generykach wyrobić.

http://www.centrumxp.pl/dotNet/715,1,17_Typy_generyczne_generics.aspx

--
PaSkol

PaSkol

unread,
Sep 10, 2010, 6:39:37 AM9/10/10
to
W dniu 2010-09-10 12:37, PaSkol pisze:

>> grzebie po googlach

W sumie wpisując do google: typy generyczne
dostaje się pokaźną ilość stron po polsku.

--
PaSkol

Arivald

unread,
Sep 10, 2010, 6:47:06 AM9/10/10
to
W dniu 2010-09-10 12:11, neuron pisze:
> witam
> moze mi ktos tak lopatologicznie wytlumaczyc o co chodzi z tymi calymi
> typami generycznymi?
> grzebie po googlach ale mam problemy zeby zatrybic (tak jak mialem problemy
> z obiektowoscia przy przechodzeniu z TP na delphi) nie tyle co to jet a po
> co to jest.
>
> Z tego co mi sie udalo doczytac a wiekszosc materalow polsko jezycznych
> (angielski znam tak slabo ze jak nie wiem o czym czytam to nic nie rozumiem)
> tyczy sie dotnetu i visuala
> a google na temat typy generyczne + delphi wyrzuca ino pochwaly d2010 dXE ze
> tez ma ;)
> doczytalem sie wiec ze typy generycnze to taka tablica (lista) gdzie mzona
> wepchnac wszstko (wszytskie typy od byte do okiektow i klas) tyle ze nie
> kumam po co

nie... możesz wepchnąć tylko jeden typ. Tyle nieznany w momencie pisanie
kodu dla listy generycznej. Włąściwy kowd wykonywalny zostanie potem
wygenerowany na podstawie kodu listy, i typu którym się skonkretyzuje listę.

dla przykładu, jak masz typ generyczny TList<T>,
to potem łatwo możesz uzysakć:
* lista kontrolek: TList<TControl> - będzie przechowywać tylko kontrolki
* list pól: TList<TField>
* lista datasetów : TList<TDataSet>
* lista wskaźników: TList<Pointer>

> Tak sobie kombinuje ze moze chodzi o to aby jedna czesc programu
> przekazywala innej czesci (lub innemu programowi w ramach autoamtyzacji) nie
> tylko dane ale tez instrukcje co z tymi danymi zrobic.
> czyli takie varianty z mozliwoscia przypisania klasy czy procedury.

Kombinujesz, jak koń pod górkę ;-)

> Zreszta z variantami tak naprawde zatrybilem o co chodzi gdy zobaczylem jak
> program przekazuje parametry do FastReporta i teraz tak sobie kombinuje ze
> moze za pomoca generykow do takiego fast reporta

Nie. Variant przechowywać może wiele różnych typów, w tym tablicę
Variantów.
Generyk tylko jeden typ, tyle że nie sprecyzowany. Typ doprecyzowuje się
w momencie konkretyzacji generyka.

Generyki to jeden ze sposobów na metaprogramowanie. Raz piszesz kod,
używasz wielokrotnie dla różnych typów.

BTW, Generyki w Delphi to pikuś. Zobaczył być co się są zrobić z ich
pierwowzorem, czyli wzorcami (templates) w C++... cudeńka. Dość
powiedzieć, ze standardowy typ stringa w C++ (std::string) jest właśnie
konkretyzacją wzorca std::basic_string<charT, traits, Alloc>, gdzie
typem konkretyzującym jest "char" i jego trait.
Jak w C++ chcesz uzyskać dowolny inny typ stringa (unikodowy, UTF-8,
BCD, 7-bit czy inny), to po prostu konkretyzujesz sobie
std::basic_string<> innym typem znaku. Zero kodowania.


--
Arivald

neuron

unread,
Sep 10, 2010, 6:57:53 AM9/10/10
to

> dla przykładu, jak masz typ generyczny TList<T>,
> to potem łatwo możesz uzysakć:
> * lista kontrolek: TList<TControl> - będzie przechowywać tylko kontrolki
> * list pól: TList<TField>
> * lista datasetów : TList<TDataSet>
> * lista wskaĽników: TList<Pointer>
>
To moze zapytam inaczej
co moge zrobic majac TLisr<Tfield> czego nie moglbym zrobic (albo musialbym
zobic mnogo kodu) majac array of Tcontrol ?


Wiktor S.

unread,
Sep 10, 2010, 7:16:33 AM9/10/10
to
>> * lista kontrolek: TList<TControl> - będzie przechowywać tylko
>> * list pól: TList<TField>
>> * lista datasetów : TList<TDataSet>
>> * lista wskaźników: TList<Pointer>

>>
> To moze zapytam inaczej
> co moge zrobic majac TLisr<Tfield> czego nie moglbym zrobic (albo
> musialbym zobic mnogo kodu) majac array of Tcontrol ?

Może zacznijmy inaczej: jest "od zawsze" w Pascalu tablica. Tablica jest
zawsze "czegoś", np. array of integer.
Teraz w generykach chodzi, aby móc samemu zadeklarować "typ czegoś". Szkoda,
że zastosowano składnię C++. Bardziej naturalnie wyglądałoby

TList of pointer

zamiast

TList<pointer>


Samo TList<T> nie daje zbyt wiele ponad tablicę dynamiczną - ale jest też
TQueue (kolejka), TStack (stos), i ciekawy typ TDictionary (tablica
asocjacyjna).

Słowem: gdy napiszemy swój własny super-magiczny czy wydajny kontener
integerów, a zachciało nam się stringów, nie musimy powielać tony kodu
zamieniając wszystkie "integer" na "string", albo stosować półśrodki w
postaci pointerów: możemy mieć natychmiast naszą kolejkę integerów,
stringów, i TButtonów.

--
Azarien

Arivald

unread,
Sep 10, 2010, 7:24:37 AM9/10/10
to
W dniu 2010-09-10 12:57, neuron pisze:

>> dla przykładu, jak masz typ generyczny TList<T>,
>> to potem łatwo możesz uzysakć:
>> * lista kontrolek: TList<TControl> - będzie przechowywać tylko kontrolki
>> * list pól: TList<TField>
>> * lista datasetów : TList<TDataSet>
>> * lista wskaźników: TList<Pointer>

>>
> To moze zapytam inaczej
> co moge zrobic majac TLisr<Tfield> czego nie moglbym zrobic (albo musialbym
> zobic mnogo kodu) majac array of Tcontrol ?
>
>

wersja z array of Tcontrol

ac: array of Tcontrol

dodanie elementu:

SetLength(ac, Length(ac) + 1);
ac[Length(ac) - 1] := someControl;

Wady:
* ręczne zarządzanie pamięcią, podatność na błędy.
* Tragiczna (!) wydajność dodawania. Za kazdym razem realokujesz.
można to zmienić, ale wtedy potrzebujesz dodatkowej zmiennej na
przechowywanie ilości zajętych elementów tablicy.


usuwanie dowolnego elementu:

for i := o to Length(ac) - 1 do
if ac[i] = someControl then
begin
//kopiowanie elementów poza usuwanym na miejsce zajmowane przez
usunięty
Move (..., ..., Length(ac) - i); //nie chce mi się teraz myśleć
jakie dokładnie parametry ... ;-)
SetLength(ac, Length(ac) - 1);
//tu ewentuaknie Break; jesli jeseś pewien ze someControl tylko
raz było w tablicy
end;

Wady:
* Jak poprzednio, ręczne zarządzanie pamięcią, podatność na błędy.
* Tragiczna wydajność.
* tablica jest wektorem: zajmuje jeden ciągły fragment pamięci.
W momencie kiedy usuwasz element ze środka to musisz kopiować czasem
spory kawałek pamięci.

-------------------------------------------------------------------------

wersja z TList<TControl>

ac: TList<TControl>;

dodanie elementu:

ac.Add(someControl);

usuwanie dowolnego elementu:

ac.Remove(someControl);

Wad żadnych nie widzę.
Dodatkowo, implementacja TList to może nie być wektor, a np linked-list,
czy hash-table, co ma ogromy wpływ na wydajność.

Przy dobrze zaprojektowanej rodzinie kontenerów (TVector<T>, TQueue<T>,
TStack<T>, THashTable<T>, TLinkedList<T>, etc) kontenery są wymienne
(mają spójne API), i można łatwo przetestować wpływ konkretnej
implementacji kontenera na wydajność w danym algorytmie.

--
Arivald


Wiktor S.

unread,
Sep 10, 2010, 7:53:52 AM9/10/10
to
> SetLength(ac, Length(ac) + 1);
> ac[Length(ac) - 1] := someControl;
>
> Wady:
> * ręczne zarządzanie pamięcią, podatność na błędy.
> * Tragiczna (!) wydajność dodawania. Za kazdym razem realokujesz.

nie? przynajmniej z analizy kodu Free Pascala kiedyś wynikło mi że nie.
Chyba że Delphi jest gorsze pod tym względem...

--
Azarien

Piotrek

unread,
Sep 10, 2010, 7:54:00 AM9/10/10
to
> wersja z TList<TControl>
>
> ac: TList<TControl>;
>
> dodanie elementu:
>
> ac.Add(someControl);
>
> usuwanie dowolnego elementu:
>
> ac.Remove(someControl);
>

Czyli za pomocą deklaracji TList<TControl> uzyskujemy listę której
elementami są obiekty TControl?
A można to zapisać jako var a: TList; jako elementy dodawane do listy
wskaźniki do innych obiektów?

wloochacz

unread,
Sep 10, 2010, 7:55:12 AM9/10/10
to
W dniu 2010-09-10 13:16, Wiktor S. pisze:

>>> * lista kontrolek: TList<TControl> - będzie przechowywać tylko
>>> * list pól: TList<TField>
>>> * lista datasetów : TList<TDataSet>
>>> * lista wskaźników: TList<Pointer>
>>>
>> To moze zapytam inaczej
>> co moge zrobic majac TLisr<Tfield> czego nie moglbym zrobic (albo
>> musialbym zobic mnogo kodu) majac array of Tcontrol ?
>
> Może zacznijmy inaczej: jest "od zawsze" w Pascalu tablica. Tablica jest
> zawsze "czegoś", np. array of integer.
> Teraz w generykach chodzi, aby móc samemu zadeklarować "typ czegoś".
> Szkoda, że zastosowano składnię C++. Bardziej naturalnie wyglądałoby
>
> TList of pointer
>
> zamiast
>
> TList<pointer>
>
>
> Samo TList<T> nie daje zbyt wiele ponad tablicę dynamiczną - ale jest
> też TQueue (kolejka), TStack (stos), i ciekawy typ TDictionary (tablica
> asocjacyjna).
Bardzo ciekawy - ciecze pamięcią jak z durszlaka.

> Słowem: gdy napiszemy swój własny super-magiczny czy wydajny kontener
> integerów, a zachciało nam się stringów, nie musimy powielać tony kodu
> zamieniając wszystkie "integer" na "string", albo stosować półśrodki w
> postaci pointerów: możemy mieć natychmiast naszą kolejkę integerów,
> stringów, i TButtonów.

Zamiast pisać, lepiej korzystać ;-)
http://code.google.com/p/delphilhlplib/wiki/FeatureList
I koniecznie zapoznać się co to jest ENEX w konwencji DeHL'a, a daje coś
takiego "Enex (Enumerable Extensions) provide Linq-like possibilities
for all DeHL collections."
Gdzie słowo-klucz to "Linq-like", co to daje?
Rzut oka na IEnexCollection<T>, gdzie można znaleźć takie metody:

function Aggregate : IEnexCollection<T>;
function Max : IEnexCollection<T>;
function Min : IEnexCollection<T>;
function Ordered : IEnexCollection<T>;
function Ordered : IEnexCollection<T>;
function Range : IEnexCollection<T>;
function Reversed : IEnexCollection<T>;
function SkipWhile : IEnexCollection<T>;
function SkipWhileBetween : IEnexCollection<T>;
function SkipWhileGreater : IEnexCollection<T>;
function SkipWhileGreaterOrEqual : IEnexCollection<T>;
function SkipWhileLower : IEnexCollection<T>;
function SkipWhileLowerOrEqual : IEnexCollection<T>;
function Union : IEnexCollection<T>;
function Where : IEnexCollection<T>;
function WhereBetween : IEnexCollection<T>;
function WhereGreater : IEnexCollection<T>;
function WhereGreaterOrEqual : IEnexCollection<T>;
function WhereLower : IEnexCollection<T>;
function WhereLowerOrEqual : IEnexCollection<T>;
function WhereNot : IEnexCollection<T>;

Proszę zwrócić uwagę, że każda metoda zwraca referencję własnego
interfejsu (tzw builder, szczegóły np. w TStringBuilder), a więc można
napisać coś takiego:

MaxValue := collection.
Where(coś tam).
Max(coś tam);

--
wloochacz

wloochacz

unread,
Sep 10, 2010, 7:58:23 AM9/10/10
to
W dniu 2010-09-10 13:54, Piotrek pisze:
/ciach/

> Czyli za pomocą deklaracji TList<TControl> uzyskujemy listę której
> elementami są obiekty TControl?

Tak.

> A można to zapisać jako var a: TList; jako elementy dodawane do listy
> wskaźniki do innych obiektów?

Deklarując zmienną typu generycznego, robisz tzw. konkretyzację - a więc
wskazujesz jakim type ma się owa konkretna instancja typu generycznego
(tu: TList<T>) posługiwać.

Możesz tam wpisać cokolwiek:
TList<Pointer> - wskaźniki na cokolwiek
TList<TObject> - referencje dowolnych obiektów


--
wloochacz

darekm

unread,
Sep 10, 2010, 8:15:25 AM9/10/10
to
W dniu 2010-09-10 12:57, neuron pisze:
>> dla przykładu, jak masz typ generyczny TList<T>,
>> to potem łatwo możesz uzysakć:
>> * lista kontrolek: TList<TControl> - będzie przechowywać tylko kontrolki
>> * list pól: TList<TField>
>> * lista datasetów : TList<TDataSet>
>> * lista wskaźników: TList<Pointer>

>>
> To moze zapytam inaczej
> co moge zrobic majac TLisr<Tfield> czego nie moglbym zrobic (albo musialbym
> zobic mnogo kodu) majac array of Tcontrol ?
>
>

Dostajesz silną kontrolę typów bez pisania tych samych algorytmów dla
różnych struktur danych.
np jeżeli tlf = tList<TField>, ds=tDataSet
to kompilator nie puści
tlf.add(ds);

obecnie albo dopuszczasz każdy obiekt, albo piszesz odrębne implementacje


--
Darek

Arivald

unread,
Sep 10, 2010, 8:15:58 AM9/10/10
to
W dniu 2010-09-10 13:54, Piotrek pisze:
>> wersja z TList<TControl>
>>
>> ac: TList<TControl>;
>>
>> dodanie elementu:
>>
>> ac.Add(someControl);
>>
>> usuwanie dowolnego elementu:
>>
>> ac.Remove(someControl);
>>
>
> Czyli za pomocą deklaracji TList<TControl> uzyskujemy listę której
> elementami są obiekty TControl?

Tak. Plus kontrolę typu elementu w trakcie kompilacji.

> A można to zapisać jako var a: TList; jako elementy dodawane do listy
> wskaźniki do innych obiektów?
>

a: TList przechowuje wskaźniki. Możesz tam dodać obiekty, ale przy
wyciąganiu nie masz gwarancji ze wskaźnik który wyciągniesz jest
obiektem, czy TControl w szczególności.

Przy TList<TControl> masz gwarancję że lista przyjmie tylko pochodne
TControl, a kompilator Cię ostrzeże jeśli spróbujesz tam przypisać coś
innego. To upraszcza wiele kodu.

Z drugiej strony, przy TList<integer> masz pewność ze w liście są tylko
liczby, a TList<string> przechowuje stringi.


--
Arivald

Wiktor S.

unread,
Sep 10, 2010, 8:48:37 AM9/10/10
to
> Z drugiej strony, przy TList<integer> masz pewność ze w liście są tylko
> liczby

właśnie: liczby, a nie wskaźniki na te liczby. odpada zbędna alokacja tego,
co może być w miejscu.


--
Azarien

Wiktor S.

unread,
Sep 10, 2010, 8:50:29 AM9/10/10
to
> Z drugiej strony, przy TList<integer> masz pewność ze w liście są tylko
> liczby

właśnie: mogą być liczby, a nie wskaźniki na te liczby. odpada zbędna

alokacja tego,
co może być w miejscu.

No, chyba że TList jest skopane pod tym względem. Byłoby szkoda. Jak jest
naprawdę: czy TList<integer> wewnętrznie przechowuje integery czy wskaźniki?


--
Azarien

Wiktor S.

unread,
Sep 10, 2010, 10:11:53 AM9/10/10
to
>> Samo TList<T> nie daje zbyt wiele ponad tablicę dynamiczną - ale jest
>> też TQueue (kolejka), TStack (stos), i ciekawy typ TDictionary
>> (tablica asocjacyjna).
> Bardzo ciekawy - ciecze pamięcią jak z durszlaka.

jakieś szczegóły?

> MaxValue := collection.
> Where(coś tam).
> Max(coś tam);


Aaale fajne... tylko dokumentacja do tego dehla jest tragiczna wręcz.


--
Azarien

Tomek D

unread,
Sep 10, 2010, 2:29:46 PM9/10/10
to
W dniu 2010-09-10 13:55, wloochacz pisze:

>> Zamiast pisać, lepiej korzystać ;-)
> http://code.google.com/p/delphilhlplib/wiki/FeatureList
> I koniecznie zapoznać się co to jest ENEX w konwencji DeHL'a, a daje coś
> takiego "Enex (Enumerable Extensions) provide Linq-like possibilities
> for all DeHL collections."
> Gdzie słowo-klucz to "Linq-like", co to daje?
> Rzut oka na IEnexCollection<T>, gdzie można znaleźć takie metody:
>
> function Aggregate : IEnexCollection<T>;
> function Max : IEnexCollection<T>;
> function Min : IEnexCollection<T>;
>......

> MaxValue := collection.
> Where(coś tam).
> Max(coś tam);
>

Właśnie przekonałeś mnie do upgrade-u Delphi

Tomek D.

wloochacz

unread,
Sep 11, 2010, 2:47:09 AM9/11/10
to
W dniu 2010-09-10 20:29, Tomek D pisze:
/ciach/

> Właśnie przekonałeś mnie do upgrade-u Delphi

Uważaj; D2010 ma problemy z zagnieżdżonymi typami generycznymi (nie da
się używać tego typu, poza modułem w którym został zadeklarowany -
internal error urw:111 - full wypas normalnie...)
D2009 w ogóle się nie da na poważnie z generyków korzystać.
Podobno (podobno, bo sam nie wiem i wolę aby inni byli beta testerami)
Delphi XE rozwiązuje w/w problemy.

--
wloochacz

wloochacz

unread,
Sep 11, 2010, 2:56:08 AM9/11/10
to
W dniu 2010-09-10 16:11, Wiktor S. pisze:

>>> Samo TList<T> nie daje zbyt wiele ponad tablicę dynamiczną - ale jest
>>> też TQueue (kolejka), TStack (stos), i ciekawy typ TDictionary
>>> (tablica asocjacyjna).
>> Bardzo ciekawy - ciecze pamięcią jak z durszlaka.
>
> jakieś szczegóły?
Było o tym głośno na blogach.
Widzę, że w QC jest poprrawka do wersji 12, nie wiem czy zostało to już
poprawione w wersji 14.
Jak się dowiem, to dam znać.


>> MaxValue := collection.
>> Where(coś tam).
>> Max(coś tam);
>
>
> Aaale fajne... tylko dokumentacja do tego dehla jest tragiczna wręcz.

Nie wiesz jak się z list kontenerów korzysta?
Tak jak sobie wymyślisz ;-)

Powiadasz, że dokumentacja jest tragiczna?
Zanim coś powiesz, zajrzyj do źródeł; WSZYSTKO jest opisane w
komentarzach do każdej metody.
Poza tym, to jest bardzo dobry kod za free - odrobina pokory.

--
wloochacz

Wiktor S.

unread,
Sep 11, 2010, 2:41:34 PM9/11/10
to
>> Aaale fajne... tylko dokumentacja do tego dehla jest tragiczna wręcz.
> Nie wiesz jak się z list kontenerów korzysta?

Nie wiem dokładnie, co tam jest. Albo co w którym unicie.

Oczywiście - są źródła. Szkoda że nie zastosowali jakiegoś systemu do
generowania dokumentacji.

--
Azarien

0 new messages