KLASY

Strona g│≤wna

 

KLASY

Klasa to obiekt, kt≤ry zawiera procedury i funkcje wsp≤│pracuj▒ce ze sbo▒. 
W prawie ka┐dym programie spotykasz siΩ z klas▒. W typowym formularzu wygl▒da ona tak:

type
  TForm1 = class(TForm)
  private
    { Private declarations }
  public
    { Public declarations }
  end;

Jest to nowa klasa "TForm1", kt≤ra dziedziczy z klasy "TForm". 

Dziedziczenie to budowanie klasy na bazie innej ju┐ istniej▒cej z przejΩciem jej procedur i funkcji. 

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