Jak widzisz w powy┐szym przyk│adzie klasa mo┐e
posiadaµ kilka sekcji tak jak: private, public
W ka┐dej z tych sekcji mo┐esz umieszczaµ swoje procedury, funkcje,
czy zmiennej, kt≤re mo┐esz wykorzystaµ w obrΩbie danej klasy.
Klasa umo┐liwia kilka poziom≤w dostΩpu do danej klasy:
-
private - umieszczaj▒c procedury czy funkcje
w tej sekcji mo┐esz byµ pewny, ┐e nie bΩd▒ one mog│y byµ
wykorzystywane przez inne klasy. Ta sekcja s│u┐y do pomocniczych
procedur i funkcji, czy zmiennych, kt≤re s▒ ukrywane dla u┐ytkownika
tej klasy.
-
public - ta sekcja jak sama nazwa wskazuje
jest sekcj▒ "publiczn▒" tzn., ┐e wszystkie procedury i
funkcje umieszczone w jej obrΩbie bΩd▒ dostΩpne dla innych klas
i u┐ytkownika.
-
protected - umieszczone w tej sekcji
procedury i funkcje s▒ mo┐liwe do wykorzystania w klasach
pochodnych tj. dziedzicz▒cych z naszej klasy;
-
published - w tej sekcji umieszczone s▒ tzw.
w│a╢ciwo╢ci, kt≤re widnieµ bΩd▒ w Inspektorze Obiekt≤w. Ta
sekcja jednak jest wykorzystywana do pisania w│asnych komponent≤w
i nie bΩdΩ jej tutaj obja╢nia│.
Wiem, ┐e teraz mo┐esz siΩ w tym wszystkim nie po│apaµ
i nie wiesz w jakiej sekcji chcesz zamie╢ciµ swoj▒ procedurΩ, ale
nie martw siΩ - z czasem pojmiesz o co chodzi i bΩdziesz "wyczuwa│"
w jakiej sekcji umie╢ciµ dan▒ procedurΩ, czy funkcje.
Ty tak┐e mo┐esz stworzyµ swoj▒ klasΩ. Oto przyk│ad:
type
TMojaKlasa = class
public
procedure Startuj;
end;
Klase deklaruje siΩ jako nowy typ czyli z u┐yciem s│owa
kluczowego type. NastΩpnie nazwa i po znaku "=" s│owo
"class" oznaczaj▒ce now▒ klasΩ. NastΩpnie mo┐esz stworzyµ
now▒ procedurΩ - np: "Startuj".
Teraz mo┐esz uzupe│niµ dan▒ procedurΩ w sekcji "Implementation":
procedure TMojaKlasa.Startuj;
begin
ShowMessage('W│asnie wystartowalem');
end;
Nic nadzwyczajnego - po prostu wy╢wietlenie
komunikatu.
To jeszcze nie wszystko. Musisz bowiem now▒ klasΩ
utworzyµ:
procedure TForm1.FormCreate(Sender: TObject);
var
MojaKlasa : TMojaKlasa; // wskazanie na nowa klase!!!
begin
MojaKlasa := TMojaKlasa.Create; // utworzenie klasy
MojaKlasa.Startuj; // uruchomienie procedury
end;
Tak zadeklarowane polecenia w procedurze "OnCreate"
bΩd▒ tworzyµ nowy egzemplarz klasy, a nastΩpnie uruchamia│y bΩd▒
one now▒ procedurΩ.
Zamiast tego mo┐esz po prostu wstawiµ s│owa kluczowe "initialization"
i "finalization" do modu│u:
implementation
{$R *.DFM}
type
TMojaKlasa = class
public
procedure Startuj;
end;
var
MojaKlasa : TMojaKlasa; // wskazanie na nowa klase!!!
procedure TMojaKlasa.Startuj;
begin
ShowMessage('W│asnie wystartowalem');
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
MojaKlasa.Startuj; // uruchomienie procedury
end;
initialization
MojaKlasa := TMojaKlasa.Create; // utworzenie egzemplarza
finalization
MojaKlasa.Free; // zwolnienie po zamkniΩciu programu
end.
Tak, klasa mo┐e byµ tak┐e deklarowana w sekcji "Implemenatation",
ale wtedy nie bΩdzie mo┐liwe jej wykorzystanie przez inne modu│y.
Teraz gdy napisa│e╢ jak▒╢ klasΩ mo┐esz utworzyµ
klasΩ pochodn▒ ( dziedzicz▒c▒ ) z przed chwil▒ utworzonej klasy:
type
TMojaKlasa = class
public
procedure Startuj;
end;
TDruga = class(TMojaKlasa)
public
procedure Laduj;
end;
Jak widaµ w przyk│adzie nowa klasa dziedziczy ze
starej. Tak - to jest dziedziczenie.
W klasach mo┐esz deklarowaµ dodatkowo kilka typ≤w
metod ( procedur i funkcji ):
-
statyczne
-
wirtualne
-
dynamiczne
Oto przyk│ady:
type
TKlasa = class
procedure Statyczna;
procedure Wirtualna; virtual;
procedure Dynamiczna; dynamic;
end;
Metody statyczne:
S▒ to zwyk│e metody, kt≤rej adres znany jest ju┐
podczas kompilacji. Jest to zwyk│a metoda, ale bardzo efektywna.
Metody wirtualne
Hmm, jak to by opisaµ. Je┐eli opatrzysz procedurΩ
klauzur▒ "virtual" masz mo┐liwo╢µ tzw. przedefiniowywania
metod. O tym dalej. Innymi s│owy je┐eli w typie macierzystym i pochodnym
( dziedzicz▒cym ) jest taka sama nazwa mo┐esz przykryµ star▒
procedurΩ na now▒. O tym dalej.
Metody dynamiczne
Dynamiczne metody nie r≤┐ni▒ siΩ zbytnio od metod
wirtualnych, ale sa mniej "pamiΩcoich│onne" od wy┐ej
wymienionej.
Przedefiniowywanie metod
Oto przyk│ad. Na pocz▒tku tworzymy klasΩ pochodn▒ i
przypisujemy procedurΩ:
type
TMojaKlasa = class
procedure Startuj; virtual;
end;
Stworzona zosta│a klasa. Opatrzona jest ona s│owem
"virtual", czyli jest to metoda wirtualna.
Tworzymy teraz now▒ klasΩ dziedzicz▒c▒ ze starej:
TDruga = class(TMojaKlasa)
procedure Startuj; override;
end;
Ta procedura mimo takiej samej nazwy opatrzona jest klauzur▒
"override". To jest w│a╢nie to s│ynne przedefiniowanie
metod - czytaj dalej...
NastΩpnie tworzymy wskazanie na owe klay:
var
MojaKlasa : TMojaKlasa;
Foo : TDruga;
Oto ca│y kod:
implementation
{$R *.DFM}
type
TMojaKlasa = class
procedure Startuj; virtual;
end;
TDruga = class(TMojaKlasa)
procedure Startuj; override;
end;
var
MojaKlasa : TMojaKlasa;
Foo : TDruga;
procedure TMojaKlasa.Startuj;
begin
ShowMessage('W│asnie wystghtowalem');
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Foo.Startuj;
end;
procedure TDruga.Startuj;
begin
inherited; // wywolanie pierwotnej procedury "Startuj"
ShowMessage('Pr≤ba nie powiod│a siΩ - wystartowa│em poraz drugi');
end;
initialization
MojaKlasa := TMojaKlasa.Create; // utworzenie egzemplarza
Foo := TDruga.Create;
finalization
MojaKlasa.Free; // zwolnienie po zamknieciu programu
Foo.Free;
end.
Gdy teraz uruchomisz program zobaczysz najpierw pierwszy
komunikat, a zaraz p≤╝niej drugi! Mimo, ┐e w procedurze "OnCreate"
wywo│a│em tylko pierwsz▒! Wszystko za spraw▒ s│≤wka "inherited".
Wywo│uje ono procedurze bazow▒.
procedure T1Klasa.Start;
begin
{ nowy kod }
end;
procedure T2Klasa.Start;
begin
inherited; { <-- wywolanie bazowej procedury }
{ nowy kod dla procedury }
end;
Innymi s│owy druga procedura unowocze╢nia starsz▒.
Konstruktory i destruktory
Normalnie jak chcesz stworzyµ jak▒╢ zmienn▒ to
piszesz:
var
B : TButton;
begin
B := TButton.Create;
To "Create" to jest w│a╢nie konstruktor
odpowiadaj▒cy za utworzenie komponentu. Ty tak┐e mo┐esz stworzyµ co╢
takiego.
Konstruktor zawsze deklaruje siΩ w sekcji "public" - np:
constructor Create; override;
Jak widzisz nie jest to zwyk│a procedura, zaczyna siΩ
bowiem od s│owa "constructor". Pewnie siΩ zastanawiasz po co
u┐yty tutaj zosta│ parametr "override". Ot≤┐ klasa bazowa
na kt≤rej siΩ opierasz tak┐e posiada taki konstruktor i je┐eli nazwa
Twojego konstruktora to "Create" musisz u┐yµ
przedefiniowania.
Destruktor natomiast zwalnia obiekt.
Oto prosty przyk│ad u┐ycia konstruktora i destruktora
- program nie robi nic specjalnego - ustawia tylko forme w pozycji przez
Ciebie ustawionej:
implementation
{$R *.DFM}
type
TKlasa = class
private
Left : Byte;
Top : Byte;
Right : Byte;
Bottom : Byte;
Tekst : PCHar;
public
procedure Ustaw;
constructor Create(L, T, R, B : Integer);
destructor Destroy; override;
end;
var
Klasa : TKlasa;
constructor TKlasa.Create(L, T, R, B: Integer);
begin
Tekst := AllocMem(1024); // przydzia│ pamiΩci
Left := L;
Top := T;
Right := R;
Bottom := B;
end;
destructor TKlasa.Destroy;
begin
FreeMem(Tekst); // zwolnienie pamiΩci
inherited; // uruchomienie destruktora klasy bazowej
end;
procedure TKlasa.Ustaw;
begin
{ Procedura ustawia formularz wedle pozycji podanych w
konstruktorze }
Form1.Left := Left;
Form1.Top := top;
Form1.Width := Right;
Form1.Height := Bottom;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Klasa := TKlasa.Create(0, 0, 100, 100); // wywo│aj konstruktor
Klasa.Ustaw; // wywo│aj procedurΩ
end;
initialization
finalization
Klasa.Free;
end.
Mo┐esz tutaj ╢ci▒gn▒µ przyk│adowy program
korzystaj▒cy z klas i modu│≤w. Jest to przyk│adowa prosta gra -
manager.
TSamoch≤d.zip ( 6 kB )
Adam Boduch