Why is this an issue?

In other languages, it is common to define a method with interface-type arguments so that it can interact with a concrete object in an encapsulated way. In Delphi, if you ever interact with an object through an interface, you should always interact with that object through an interface so that reference counting semantics are not unexpectedly violated.

Assigning an object reference to an interface-type variable in Delphi causes that object to become reference counted (i.e. the object will be automatically destroyed when there are no longer any in-scope references). Only references through interface-type variables increment and decrement the reference count, so direct object references will not be counted. When used carelessly, this can lead to memory issues and access violations. For example:

procedure ReadManualFor(Appliance: IAppliance);
begin
  // ...
end;

procedure Example;
var
  TV: TTelevision;
begin
  TV := TTelevision.Create;
  ReadManualFor(TV);
  WriteLn(TV.Brand); // Access violation!
end;

How to fix it

The concrete-typed variable should be changed to an interface type if possible:

procedure ReadManualFor(Appliance: IAppliance);

procedure Example;
var
 TV: TTelevision;
begin
  TV := TTelevision.Create;
  TV.ConnectAerial;
  ReadManualFor(TV);
  WriteLn(TV.Brand);
end;
procedure ReadManualFor(Appliance: IAppliance);

procedure Example;
var
 TV: IAppliance;
begin
  TV := TTelevision.Create;
  TTelevision(TV).ConnectAerial;
  ReadManualFor(TV);
  WriteLn(TV.Brand);
end;

If keeping a direct object reference is really important, cast the variable to make the new semantics clear:

procedure ReadManualFor(Appliance: IAppliance);

procedure Example;
var
 TV: TTelevision;
begin
  TV := TTelevision.Create;
  TV.ConnectAerial;
  ReadManualFor(TV);
  WriteLn(TV.Brand);
end;
procedure ReadManualFor(Appliance: IAppliance);

procedure Example;
var
 TV: TTelevision;
begin
  TV := TTelevision.Create;
  TV.ConnectAerial;
  ReadManualFor(IAppliance(TV));
  WriteLn(TV.Brand);
end;

Resources