W Pascalu istnieje konstrukcja class of
, która umożliwia deklarację typu danych, służącego do przechowywania referencji klasy (klasy, nie instancji klasy zwanej obiektem). Taki typ danych może być później użyty w jakichś fabrykach, np. w parametrze metody wypluwającej obiekty — podaje się w parametrze klasę, ona zostaje użyta do stworzenia instancji (obiektu) i zwrócenia referencji.
Zróbmy przykład. Mamy bazową klasę przedmiotu — ma ona wspólne dane, tutaj nazwę:
type
TCustomItem = class(TObject)
public
Name: String;
end;
Teraz zadeklarujmy kilka klas konkretnych przedmiotów, dziedziczących z bazowej klasy:
type
TOrange = class(TCustomItem);
TBanana = class(TCustomItem);
Wszystkie te klasy dziedziczą pole Name
, więc każda posiada swoją nazwę. Aby móc wygodnie tworzyć instancje tych owoców, przyda się metoda (jedna), która będzie pobierać w parametrze referencję klasy i nazwę, będzie tworzyć instancję, uzupełniać wspólne dane i finalnie zwracać obiekt. Najpierw potrzebujemy typu danych, dzięki któremu możliwe będzie przekazanie referencji klasy:
type
TCustomItemClass = class of TCustomItem;
Zmienna tego typu może przyjąć referencję dowolnej klasy, zarówno TCustomItem
, jak i każdej z niej dziedziczącej. Ostatnim krokiem jest napisanie kodu funkcji tworzącej i wypluwającej obiekty owoców:
function CreateItem(AClass: TCustomItemClass; const AName: String): TCustomItem;
begin
Result := AClass.Create();
Result.Name := AName;
end;
Jak widać, wewnątrz tej funkcji nie wiemy jaką klasę poda użytkownik. Do stworzenia instancji używamy klasy podanej w parametrze AClass
i inicjalizujemy tylko te pola, które istnieją w klasie bazowej. I teraz przykład użycia:
var
Items: TItems;
Item: TCustomItem;
begin
Items := TItems.Create();
try
Items.Add(CreateItem(TOrange, 'orange'));
Items.Add(CreateItem(TBanana, 'banana'));
Items.Add(CreateItem(TCustomItem, 'custom'));
for Item in Items do
WriteLn(Item.Name);
finally
Items.Free();
end;
end.
Jak widać funkcja CreateItem
tworzy instancje zadanych klas i referencje obiektów lądują w liście. Na wyjściu dostaniemy:
orange
banana
custom
Pełny kod testowy znajdziecie tutaj — https://ideone.com/b2Fa2N
Skoro wiemy już jak to działa, teraz pytanie — czy w C++ jest odpowiednik pascalowego class of
, czyli konstrukcja pozwalająca zadeklarować typ danych do przechowywania referencji klasy? Kolega pyta jakby co. ;)