Metody klasowe mogą być wywoływane nawet bez uprzedniego stworzenia
egzemplarza danej klasy, a w przypadku istnienia takich egzemplarzy implementacja
tych metod jest współdzielona przez wszystkie te egzemplarze. Metody klasowe zawie-
rają jednak specjalny i ukryty parametr , który jest przekazywany przez kompilator
celem zapewnienia możliwości wywoływania polimorficznych (wirtualnych) metod
klasowych. Dodatkowo metody klasowe mogą być wirtualne. Elementy nieklasowe lub
niestatyczne są niedostępne z poziomu ciała metody klasowej.
%
#1#!! jest prawdziwą, zgodną ze specyfikacją platformy .NET metodą statyczną.
Podobnie jak pola statyczne implementacja metod tego typu jest współdzielona przez
wszystkie egzemplarze danej klasy. Oznacza to, że elementy niestatyczne są niedostępne
z poziomu ciała metody statycznej. Do metod statycznych nie jest przekazywany parametr
, zatem metody niestatyczne nie mogą być wywoływane przez metody statyczne.
132
Część II Język programowania Delphi for .NET
%
#1#!" jest metodą wirtualną. Metody tego typu są wywoływane w taki sam spo-
sób jak metody statyczne, jednak z uwagi na brak możliwości przykrywania metod wirtu-
alnych, kompilator „nie zna” adresu konkretnej metody wirtualnej w momencie jej wy-
wołania w kodzie programu. W związku z tym stosowany w środowisku .NET kompilator
JIT buduje specjalną tablicę metod wirtualnych (ang. Virtual Method Table — VMT),
która w czasie wykonywania aplikacji jest przeszukiwana pod kątem adresów wywoły-
wanych funkcji wirtualnych. Przez tę tablicę muszą przejść wszystkie pojawiające się
w czasie wykonywania programu wywołania metod wirtualnych. Tablica VMT dla obiektu
zawiera nie tylko informacje na temat wszystkich deklarowanych w tym obiekcie funkcji
wirtualnych, ale dane o wszystkich takich funkcjach deklarowanych w jego przodkach.
%
#1#?1 jest metodą dynamiczną. Inaczej niż kompilator Win32 (który zapewniał
osobny mechanizm obsługi metod dynamicznych), kompilator .NET odwzorowuje me-
tody dynamiczne w odpowiednie metody wirtualne.
% $'
#1# & jest metodą obsługującą komunikaty. Użyta dyrektywa 1& powoduje utworzenie metody, która może odpowiadać na dynamicznie pojawiające się komunikaty.
Wartość zadeklarowana bezpośrednio za słowem 1& określa, na jakie komunikaty dana
metoda będzie odpowiadała. W komponentach udostępnianych przez bibliotekę VCL
metody obsługujące komunikaty są wykorzystywane do generowania automatycznych
odpowiedzi na komunikaty systemu Windows, zatem w ogólności nie są bezpośrednio
wywoływane przez programistów.
!
Przykrywanie metod jest oferowaną w języku Delphi implementacją koncepcji polimorfi-
zmu — jednego z podstawowych elementów metodologii programowania obiektowego.
Dzięki technice przykrywania metod możemy modyfikować działanie metod na po-
szczególnych poziomach dziedziczenia. Język programowania Delphi umożliwia przy-
krywanie tylko tych metod, które zostały wcześniej zadeklarowane jako wirtualne (!"),
dynamiczne (?1 ) lub jako metody obsługujące komunikaty (1&). Aby przykryć
metodę wirtualną lub dynamiczną, wystarczy w typie obiektu potomnego zamiast słowa
dyrektywy !" lub ?1 użyć dyrektywy . Aby przykryć metodę obsłu-
gującą komunikaty, w klasie potomnej należy powtórzyć dyrektywę 1& wraz z tym
samym identyfikatorem komunikatu, który użyto w klasie macierzystej (bazowej).
Przykładowo, za pomocą poniższej deklaracji klasy potomnej (' możemy przy-
kryć metody #1#!", #1#?1 i #1# & zadeklarowane wcześniej
w klasie bazowej (:
#H5< #
"AA; 69 6
"AA$ 69 6
"AA( 9 (8( 6 I(e4'(%(%44Ac%6
6
Rozdział 5. Język Delphi
133
Dyrektywa zastępuje w tablicy VMT wpis dotyczący oryginalnej metody infor-
macjami o nowej metodzie. Gdybyśmy ponownie zadeklarowali metody #1#!"
i #1#?1 ze słowami kluczowymi !" lub ?1 zamiast dyrektywy ,
stworzylibyśmy nowe metody, zamiast przykryć odpowiednie metody klasy bazowej
(. Taki zabieg zazwyczaj będzie powodował wygenerowanie ostrzeżenia kompilatora,
chyba że wcześniej dodamy do deklaracji tych metod dyrektywę !" (omówio-
ną krótko w dalszej części tego podrozdziału). Należy także pamiętać, że próba przy-
krycia w typie potomnym standardowej metody spowoduje, że metoda statyczna w nowej
klasie sprawi, że metoda ta nie będzie dostępna dla użytkowników klasy potomnej.
! '
Podobnie jak zwykłe funkcje i procedury języka Delphi, także metody mogą być prze-
ciążane, co oznacza, że pojedyncza klasa może zawierać wiele metod o tej samej nazwie
i różnych listach parametrów. Przeciążane metody muszą być oznaczane dyrektywą
, chociaż stosowanie tej dyrektywy dla pierwszego wystąpienia danej nazwy
metody w hierarchii klas jest opcjonalne. Poniższy fragment kodu jest przykładem de-
klaracji klasy zawierającej trzy metody przeciążone:
4H <
A(5"8" 69 6
A(548 69 6
A(5$8$-69 6
6
!
Może się zdarzyć, że będziesz chciał w taki sposób dodać metodę do jednej ze swoich
klas, aby zastąpić metodę wirtualną o takiej samej nazwie, którą zadeklarowano w wy-
korzystywanej klasie bazowej. W takim przypadku nie powinieneś przeciążać oryginalnej
metody udostępnianej przez klasę bazową — lepszym rozwiązaniem jest jej całkowite
ukrycie i zastąpienie nową metodą. Jeśli po prostu dodasz nową metodę i skompilujesz
swój program, kompilator wygeneruje ostrzeżenie wyjaśniające, że nowa metoda ukrywa
identycznie nazwaną metodę klasy bazowej. Aby przerwać generowanie tego typu ostrze-
żeń, w deklaracji metody w klasie potomnej powinieneś użyć dyrektywy !" .
Poniższy fragment kodu przedstawia przykład prawidłowego wykorzystania tej dyrektywy:
4G <
H 69 6
6
4H <
H 6 6
6
134
Część II Język programowania Delphi for .NET
! "
Niejawnie deklarowana zmienna nazwana jest dostępna wewnątrz wszystkich metod
obiektów. jest referencją do tego egzemplarza klasy, za pośrednictwem którego
wywołano daną metodę. Zmienna jest przekazywana przez kompilator do wszystkich
metod w postaci ukrytego parametru. Odpowiednikiem zmiennej referencyjnej
w języku C# jest zmienna !', natomiast w języku Visual Basic .NET jest to zmienna .
(. !