At compile time we will not always know the exact class that an object belongs to. For example, consider the following code using the TShape, TRectangle, and TCircle classes from previous sections.
function GetShape(Index : Integer) : TShape;
begin
  case Index of
    0: Result := TRectangle.Create;
    1: Result := TCircle.Create;
  end;
end;

var
  Shape : TShape;
  Reponse : Integer;
begin
  Writeln('Which shape do you want to draw?');
  Writeln('0 = Rectangle  1 = Circle');
  Writeln('Enter 0 or 1: ');
  Readln(Response);
  Shape := GetShape(Index);
end.
This program asks the user to enter a 0 or 1 to draw a rectangle or circle, respectively. The GetShape function will return an object of the TRectangle class if 0 is passed to it or an object of the TCircle class if 1 is passed. Since the user could enter either, we do not know at compile time what will be contained in Shape. What's more, even if we did know that the user always picks rectangles, the compiler will not let us access the fields Width or Height because these no not exist at the time TShape was defined.

The first problem, knowing what the actual class of Shape is, can be solved using the is operator:
if Shape is TRectangle then
  begin
  end
  else if Shape is TCircle then
  begin
  end;
The is operator would have also returned True for Shape is TShape since this is a true statement: Shape is indeed a member of the TShape class. The second problem, accessing methods of TRectangle once we know that the object belongs to that class, is addressed by using type casting. Type casting allows us to coerce the compiler into allowing some data (a variable for example) be treated as a type other than how it is defined. For example, the following code will throw a compiler error:
if Shape is TRectangle then
  begin
    Shape.Width := 10;
  end;
The reason is that the field Width does not exist on the ancestor type TShape which is the type with which Shape was defined. However, if we type cast Shape to TRectangle we then get access to the Width field:
if Shape is TRectangle then
  begin
    TRectangle(Shape).Width := 10;
  end;
When using type casting, it is very important to make sure we are casting to the correct type. Type casting is basically overriding the compiler's judgement. This is why we test using Shape is TRectangle first. Think of what would happen if we simply wrote the code as the following:
TRectangle(Shape).Width := 10;
The code would work just fine as long as the user picks rectangles, but as soon as a circle is picked the program throws a runtime error because the Width field does not exist on TCircle. A runtime error is a best-case scenario. Sometimes the program doesn't fail, but some data in memory has been silently corrupted. This will result in a hard-to-diagnose bug later on as the program runs. Thus, type casting can be a powerful technique, but it should be used with care. It should also be noted that type casting is not restricted to objects. Ordinal types can also be type cast; Integers can be type cast to Bytes for example. However, objects are the most common use of type casting. And, nonsensical type casts such as String to Integer will not work. The reason is, again, that type casting simply overrides the complier's judgement about the identity of a type. It does not actually do any transformation to data stored in memory. So the data represented by '3' is a character string and cannot be coerced to integer data by using Integer('3'). Instead, you need a function that actually transforms the data such as StrToInt('3').