Home > Mobile >  Am I doing something wrong with Delphi 11 and Typecasting?
Am I doing something wrong with Delphi 11 and Typecasting?

Time:02-11

If I create a simple set of classes as follows:

type
  TBase = class(TObject)
    function BaseFunction : boolean;
  end;

  TBase1 = class(TBase)
    function Base1Function : boolean;
  end;

  TBase2 = class(TBase1)
    function Base2Function : boolean;
  end;

Why do I get an Invalid Typecast Error when I try and do the following?

procedure TForm1.FormCreate(Sender: TObject);
var
  T1 : TBase2;
begin
  T1 := TBase.Create as TBase2;  
end;

Is it fixable? I feel like I'm missing something so obvious, but I just can't see it. I'm positive this worked in previous Delphi versions.

CodePudding user response:

You cannot cast an instance of a parent to an instance of a child. That's not how it works.

You can cast an instance of a class in a variable of a parent type to the type of the child, as long as the variable is created as an instance of the child.

If we take the usual example of

TAnimal = CLASS
...
          END;
TDog    = CLASS(TAnimal)
...
          END;
TCat    = CLASS(TAnimal)
...
          END;

then the following applies:

VAR
  Animal : TAnimal;
  Dog    : TDog;
  Cat    : TCat;
...
Animal:=TAnimal.Create;
Dog:=Animal AS TDog; // Cannot work - Animal can be either a Cat or a Dog
...
Animal:=TCat.Create;
Cat:=Animal AS TCat; // Works - Animal *is* a TCat.
Dog:=Animal AS TDog; // Cannot work - you can't convert a Cat to a Dog
...
Cat:=TCat.Create;
Animal:=Cat;         // Works - A Cat *is* an Animal
Dog:=Cat AS TDog;    // Cannot work - you can't convert a Cat to a Dog

The important thing is the declared type of a class instance, and the actual type of a class instance. A variable with a declared type of a parent type can potentially point to an actual type of all child classes. It all depends on the type the variable of the parent type declaration is assigned at the construction time (which can be either the parent type or any of the child types).

On the other hand, a variable of the declared type of a child cannot point to an instance of a parent (unless you force it to by hard casting). The type compatibility is only in the downwards (towards children and grandchildren) direction, and not in the upwards (towards parents and grandparents) direction.

What you are attempting is to convert a parent instance (TBase.Create makes the instance a TBase class) to a child class. This is analogous to converting a TAnimal to a TCat or TDog.

And no - the thing you are attempting has never worked in any OO (Object Oriented) language - that's simply not how OO is functioning.

  • Related