Static specifier and overriding class methods

9

I’ve encountered an interesting problem while overriding virtual class method. Consider the next program:

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  TBase = class
    class function GetName: string; virtual;
    class procedure Test; static;
  end;

  TChild = class(TBase)
    class function GetName: string; override;
  end;

class function TBase.GetName: string;
begin
  Result:= 'TBase';
end;

class procedure TBase.Test;
begin
  Writeln(GetName);
end;

class function TChild.GetName: string;
begin
  Result:= 'TChild';
end;

begin
  TBase.Test;
  TChild.Test;
  Readln;
end.

Despite the GetName function is overridden in TChild class the output is
StaticBug

The bug is static specifier of the TBase.Test method. After the specifier is removed the output is as expected:
StaticOut

The reason of the above compiler behavior is clear – with static specifier in TBase.Test method declaration the compiler (Delphi XE was used) receives no class information and statically binds TBase.GetName class method. The bad thing is that the compiler is silent about the problem and issues no warning.

Advertisements

On the future Delphi type system

6

Recent post by Allen Bauer announced that some future Delphi release will introduce “rooted” type system so that every type will be derived from TObject. It does not mean that plain old types like Integer will actually be implemented as TObject descendants. As far as I could understand code like this

Var I: LongInt;
  ...
  I:= 2;
  I:= I * 4;
  ...

will treat the variable I as a plain 32-bit value as before, but code like this

Var I: LongInt;
    S: string;
  ...
  I:= 2;
  S:= I.ToString;
  ...

will probably create a “wrapper” object for integer type internally to implement ToString method.

I want to make two remarks to the above.

The first is about terminology. I never seen it explained in Delphi books or documentation but well, instance of every type is an object. Code

Var I: Integer;

declares object of integer type. There are two different kinds of type – value types and reference types. Byte, Word, Integer, record and many more Delphi types are value types. A variable of a value type is an object itself. Reference types in Delphi are string, dynamic array, class and interface. A variable of reference type is a pointer to object.

Second, rooted type system is not the only possible approach to bring order into the type system. The concept that makes you stunned at the first acquaintance with Haskell is “type classes”. In Haskell every type is an instance of a type class; and a type can be an instance of many type classes at once. For example Integer type in Haskell is an instance of “show” type class, so integers can be converted to strings; Integer type is also an instance of “read” type class so strings can be converted to integers.