Referencje do klas w Delphi

2007-08-20 11:30

W ramach kontynuacji przeglądu nietypowych konstrukcji językowych – który to nieopatrznie rozpocząłem, zajmując się pętlami w Pythonie – obejrzymy sobie jeden z elementów języka Object Pascal. Są to referencje do klas, zwane też czasem metaklasami.

Ten dziwny twór działa jak odwołanie wskazujące na klasę jako typ, a nie na jej konkretny obiekt. Deklaruje się go mniej więcej w taki sposób:
[delphi]type TClass = class of TObject;[/delphi]
Zmienne należące do tak zdefiniowanego typu TClass mogą pokazywać na wszystkie klasy dziedziczące po TObject. Innymi słowy, takie zmienne są swego rodzaju dynamicznymi aliasami na nazwy klas; używając ich, nie musimy nawet wiedzieć, z jakiego typu klasą konkretną mamy do czynienia. Przypomina to oczywiście normalny dynamiczny polimorfizm obiektów, osiągany przy pomocy funkcji wirtualnych. Tutaj jest to niejako dynamiczny polimorfizm samych klas.

Użycie takiego typu referencyjnego może wyglądać choćby tak:
[delphi]type TFoo = class(TObject) // klasa dziedzicząca po TObject
// …
end;

var
AnyClass : TClass; // zmienna będąca referencją do klasy
AnyObject : TObject; // zwykłe odwołanie do obiektu
begin
AnyClass := TFoo; // referencja pokazuje na klasę TFoo
AnyObject := AnyClass.Create; // tworzy obiekt klas TFoo przy pomocy referencji
end;[/delphi]
Ten przykład pokazuje, że w Delphi przy pomocy referencji do klas możliwe jest łatwe zrealizowanie wzorca wirtualnego konstruktora. Nie musimy bowiem wiedzieć, na jaką klasę wskazuje referencja, a utworzony obiekt możemy “odebrać” posługując się zmienną typu bazowego (tutaj TObject).

Co na to C++? Nie ma tam naturalnie podobnej konstrukcji. Zbliżone do niej – w sensie możliwości korzystania z jakiegoś typu bez wiedzy, czym on naprawdę jest – są parametry szablonów. Podstawowa różnica polega jednak na tym, że szablony są rozwijane w trakcie kompilacji i “wartości” tych parametrów są niezmienne.
Nie wiem, czy można w jakiś sposób zaimplementować w C++ metaklasy o funkcjonalności zbliżonej do powyższej. Znając możliwości C++, to całkiem prawdopodobne :) Ich ewentualny brak nie były jednak jakoś szczególnie dotkliwy, gdyż większość ich zastosowań z powodzeniem daje się zastąpić szablonami lub zwykłymi funkcjami wirtualnymi.

Tags: , ,
Author: Xion, posted under Programming »


4 comments for post “Referencje do klas w Delphi”.
  1. Kurak:
    August 20th, 2007 o 15:52

    Tylko czemu ja nie widzę żadnego zastosowania dla tej “techniki”? ;)

  2. Xion:
    August 20th, 2007 o 18:56

    W helpie można zobaczyć np. taki przykład:

    [delphi]type TControlClass = class of TControl;

    function CreateControl(ControlClass: TControlClass;
    const ControlName: string; X, Y, W, H: Integer): TControl;
    begin
    Result := ControlClass.Create(MainForm);
    with Result do
    begin
    Parent := MainForm;
    Name := ControlName;
    SetBounds(X, Y, W, H);
    Visible := True;
    end;
    end;

    // użycie – tworzy editbox
    CreateControl(TEdit, ‘Edit1’, 10, 10, 100, 20);[/delphi]

    W C++ coś podobnego możnaby zrobić szablonem:

    1. template <class _Control> IControl* CreateControl(const String& strName, const RECT& rcBounds)
    2. {
    3.    IControl* pCtl = new _Control(strName);
    4.    pCtl->SetBounds (rcBounds);
    5.    return pCtl;
    6. }
    7.  
    8. // użycie
    9. CreateControl<CEdit>("Edit1", RECT(10, 10, 100, 20));

    Różnica jest taka, że tutaj musimy znać docelowy typ w czasie kompilacji.

  3. Spook:
    June 16th, 2010 o 19:44

    @Kurak: Może nie brałeś udziału w bardziej zaawansowanych projektach? Mnie taka konstrukcja bardzo się przydaje – choćby do automatycznego pilnowania, żeby na liście były obiekty konkretnego typu.

    Pozdrawiam — Spook.

Comments are disabled.
 


© 2017 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.