17 Mei 2009

Implementasi Run-Time Type Information / RTTI (Bagian 1)

Dengan mengetahui teknologi RTTI, kita bisa melakukan banyak hal dalam aplikasi yang kita buat. Tiap komponen VCL yang ada pada Delphi diturunkan dari class TObject. Pada class ini terdapat fungsi ClassName yang mengembalikan nama class pada obyek yang bersangkutan. Dengan mengetahui nama class pada saat run-time kita bisa melakukan pengecekan terhadap sebuah obyek yang mempunyai tipe TObject. Misalnya jika kita tahu sebuah obyek mempunyai tipe TEdit atau turunannya maka kita tahu bahwa obyek tersebut mempunyai properti Text yang bisa kita ganti. Akses terhadap obyek dapat kita lakukan dengan menggunakan operator as dan is.
procedure SetText(aObject: TObject; const aText: string);
begin
  if aObject is TEdit then
    (aObject as TEdit).Text := aText;
end;

Operator is melakukan pengecekan tipe secara dinamik terhadap suatu obyek pada saat run-time. Hasil dari pengecekan tersebut akan menghasilkan nilai True bila obyek yang dibandingkan merupakan instance dari class yang dimaksud atau salah satu turunan dari class tersebut, atau nilai False jika sebaliknya. Jika obyek tersebut berisi nilai nil, juga menghasilkan nilai False. Sedangkan operator as digunakan untuk type casting, yang akan mengembalikan referensi dari suatu obyek dengan tipe class yang diberikan.
Contoh lain kegunaan dari RTTI adalah pada tipe enumerasi. Tipe enumerasi merupakan sekumpulan nilai yang di representasikan dengan identifier yang menggambarkan nilainya. Misalnya jika kita sering bekerja dengan form, pada Object Inspector terdapat properti WindowState yang bisa berisi wsNormal, wsMinimized, atau wsMaximized. Tiap identifier tersebut di deklarasikan pada bagian type, seperti dapat kita lihat pada unit Forms dari Delphi.
type
  TWindowState = (wsNormal, wsMinimized, wsMaximized);

Nilai pada tiap identifier tersebut diwakili oleh sebuah nilai Integer yang dimulai dari 0. Jadi nilai wsNormal = 0, wsMinimized = 1, dan wsMaximized = 2. Nilai integer dari properti obyek yang memiliki tipe enumerasi bisa kita dapatkan dengan menggunakan fungsi Ord.
ShowMessage(IntToStr(Ord(Form1.WindowState)));

Sebaliknya untuk mendapatkan identifier dari tipe enumerasi, kita bisa menggunakan fungsi GetEnumName yang disediakan pada unit TypInfo.
uses TypInfo;

var
  i: Integer;
begin
    for i := Ord(Low(TWindowState)) to Ord(High(TWindowState)) do
    ShowMessage(GetEnumName(TypeInfo(TWindowState), i));
end;

Hasil yang sama kita dapatkan dengan skrip sebagai berikut.
uses TypInfo;

var
  ws: TWindowState;
begin
  for ws in [Low(TWindowState)..High(TWindowState)] do
    ShowMessage(GetEnumName(TypeInfo(TWindowState), Integer(ws)));
end;
Fungsi GetEnumName digunakan untuk mendapatkan nama tipe enumerasi berdasarkan nilai integer dan mempunyai sintaks seperti ini.
function GetEnumName(TypeInfo: PTypeInfo; Value: Integer): string;

Parameter TypeInfo merupakan pointer ke sebuah record yang berisi informasi tentang tipe enumerasi, dan parameter Value merupakan nilai integer yang mewakili tipe enumerasi. Deskripsi record tersebut terdapat pada unit TypInfo.
type
  TTypeKind = (tkUnknown, tkInteger, tkChar, tkEnumeration, tkFloat, tkString, tkSet, tkClass, tkMethod, tkWChar, tkLString, tkWString, tkVariant, tkArray, tkRecord, tkInterface, tkDynArray);
  PTypeInfo = ^TTypeInfo;
  TTypeInfo = record
    Kind: TTypeKind;
    Name: ShortString;
  end;

Untuk mendapatkan nilai integer dari suatu tipe enumerasi, menggunakan fungsi GetEnumValue dengan sintaks sebagai berikut.
function GetEnumValue(TypeInfo: PTypeInfo; const Name: string): Integer;

Misalnya mendapatkan nilai integer dari wsMaximized:
ShowMessage(IntToStr(GetEnumValue(TypeInfo(TWindowState), 'wsMaximized')));

Tidak ada komentar:

Posting Komentar