TObject a jeho metody

vložil Radek Červinka 24. května 2010 23:38

Veskrze každý zná základní třídu TObject a její metody jako Free, constructor Create a destructor Destroy. Asi znáte i užitečnou class function ClassName, která vrací název třídy a sem tam šikovné metody ClassType a ClassParent, které vrací TClass, tj. referenci na třídu za běhu.

Rád bych upozornil na některé zajímavé elementy deklarace TObject. Níže je deklarace třídy tak, jak je v Delphi 2010.

Modří již vědí, že v Delphi 2009 došlo k rozšíření o čtyři kousky a to o class function UnitName a tři virtuální metody - Equals, GetHashCode a ToString - velmi užitečné a navíc prudce zvyšující kompatibilitu s Delphi Prism a .NET.

Delphi 2010 jen navíc určuje viditelnost na public (asi vzhledem k novému RTTI) a ClassInfo je inline.

Deklarace TObject

  TObject = class
  public
    constructor Create;
    procedure Free;
    class function InitInstance(Instance: Pointer): TObject;
    procedure CleanupInstance;
    function ClassType: TClass; inline; 
    class function ClassName: string;
    class function ClassNameIs(const Name: string): Boolean;
    class function ClassParent: TClass;
    class function ClassInfo: Pointer; inline;
    class function InstanceSize: Longint; inline;
    class function InheritsFrom(AClass: TClass): Boolean;
    class function MethodAddress(const Name: ShortString): Pointer; overload;
    class function MethodAddress(const Name: string): Pointer; overload;
    class function MethodName(Address: Pointer): string;
    function FieldAddress(const Name: ShortString): Pointer; overload;
    function FieldAddress(const Name: string): Pointer; overload;
    function GetInterface(const IID: TGUID; out Obj): Boolean;
    class function GetInterfaceEntry(const IID: TGUID): PInterfaceEntry;
    class function GetInterfaceTable: PInterfaceTable;
    class function UnitName: string;
    function Equals(Obj: TObject): Boolean; virtual;
    function GetHashCode: Integer; virtual;
    function ToString: string; virtual;
    function SafeCallException(ExceptObject: TObject;
      ExceptAddr: Pointer): HResult; virtual;
    procedure AfterConstruction; virtual;
    procedure BeforeDestruction; virtual;
    procedure Dispatch(var Message); virtual;
    procedure DefaultHandler(var Message); virtual;
    class function NewInstance: TObject; virtual;
    procedure FreeInstance; virtual;
    destructor Destroy; virtual;
  end;

Jak jsem řekl, ClassType je málo využívaná, většinou si člověk vystačí s is a as, ale např. můžete mít za běhu seznam tříd (ne objektů) a v kombinaci s ClassName vybrat požadovanou třídu a její referenci získanou právě přes ClassType předat dále ke zpracování atd.

ClassParent jsem použil např. tak, že jsem měl definován seznam názvů tříd formulářů a k nim definovanou externě ikonu. A při požadavku na vznik některého následníka, jsem našel poslední definovanou ikonu v hierarchii požadované třídy. Ale určitě Vás napadne i jiné použití.

ClassInfo vrací ukazatal na RTTI. Pro pěknou práci s RTTI slouží jednotka typinfo a už tu RTTI bylo. InstanceSize vrací překvapivě velikost instance. writeln(TObject.InstanceSize); vrátí 8 byte.

TObject.AfterConstruction a TObject.BeforeDestruction

AfterConstruction a BeforeDestruction jsou volány v patřičných okamžicích, ve VCL jsou používány např. na vytvoření TForm.OnCreate. Podle helpu BeforeDestruction není volán, pokud došlo v konstruktoru k výjimce.

type
  TDemoObject = class (TObject)
  public
    constructor Create;
    destructor Destroy; override;
    procedure AfterConstruction; override; // po posledním konstruktoru
    procedure BeforeDestruction; override;
  end;

{ TDemoObject }

procedure TDemoObject.AfterConstruction;
begin
  writeln('AfterConstruction');
end;

procedure TDemoObject.BeforeDestruction;
begin
  writeln('BeforeDestruction');
end;

constructor TDemoObject.Create;
begin
   writeln('Create');
end;

destructor TDemoObject.Destroy;
begin
  writeln('Destroy');
  inherited;
end;

begin
  with TDemoObject.Create do
    Free;
end.

Výsledek běhu:

Create
AfterConstruction
BeforeDestruction
Destroy

TObject.UnitName

UnitName by neměl ničím překvapit.

program Muj.Cool.Project.SP2;
{$APPTYPE CONSOLE}
uses
  SysUtils;
type
  TDemoObject = class (TObject);
begin
  writeln(TDemoObject.UnitName);
end.

Vypíše: Muj.Cool.Project.SP2, čímž se nenápadně dostáváme k tomu, že názvy jednotek mohou být strukturované.

TObject.Equals

Nová metoda, která vrací zda jsou instance stejné. V základu toho moc neumí, ale jelikož je virtuální tak se otevírají zajímavé možnosti.

function TObject.Equals(Obj: TObject): Boolean;
begin
  Result := Obj = Self;
end;

TObject.ToString

Základní implementace volá ClassName tj. název třídy.

function TObject.ToString: string;
begin
  Result := ClassName;
end;

Mezi třídy, které ji předefinovávají patří třeba TStringWriter nebo Exception.

TObject.GetHashCode

Opět nová virtuální metodu, která vrací integer s hashcode. Základní implementace:

function TObject.GetHashCode: Integer;
begin
  Result := Integer(Self);
end;

Osobně nechápu proč není nějaká jednoduchá funkce na získání hashe stringu ( - už jsem ji našel, viz dále), takže použijte následující kód.

program TestHash;

{$APPTYPE CONSOLE}
uses
  Generics.Defaults;

function GetHashCode(const s:AnsiString):Integer;
begin
  Result := BobJenkinsHash(s[1], Length(s) * SizeOf(s[1]), 0);
end;

begin
  writeln(GetHashCode('delphi.cz'));
end.

No a nebo použijte SysUtils.HashName - writeln(HashName('delphi.cz'));

Tagy: , , , ,

Praxe

Komentování ukončeno

Naše nabídka

MVP
Ing. Radek Červinka - Embarcadero MVP
profil na linkedin, Twitter:@delphicz

Nabízím placené poradenství a konzultace v oblasti programování a vývoje SW.
Dále nabízíme i vývoj speciálního software na zakázku.

Neváhejte nás kontaktovat (i ohledně reklamy).

love Delphi

O Delphi.cz

Delphi je moderní RAD nástroj podporující tvorbu nativních aplikací pro platformu Win32, Win64, Mac OSX, Linux a na iPhone a Android.

Delphi.cz je nezávislý portál pro uživatele Delphi. Portál není koncipován pro úplné začátečníky, i když i ti se zde nebudou nudit, ale spíše na programátory, kteří již něco znají a chtějí své znalosti dále rozvíjet a sledovat novinky.

Poslední komentáře

Comment RSS

Dle měsíců