Если посмотреть, что вызывается под капотом для случая с интерфейсами, то можно увидеть:
1. Для вызова Interface1(Instance), вызывает системный метод _IntfCopy, который по сути не проверяет типы, а просто увеличивает счетчик типов. Такое приведение типов не проверяет типы, а просто копирует указатель а реализацию.
procedure _IntfCopy(var Dest: IInterface; const Source: IInterface);
{$IFDEF PUREPASCAL}
var
P: Pointer;
begin
P := Pointer(Dest);
if Source <> nil then
Source._AddRef;
Pointer(Dest) := Pointer(Source);
if P <> nil then
IInterface(P)._Release;
end;
{$ELSE}
2. При использовании оператора as будет вызван _IntfCast, который выполняет честное приведение типов через QueryInterface. Поэтому в этом случае вы получите на выходе честный указатель на таблицу интерфейса, если интерфейс поддерживается объектом.
procedure _IntfCast(var Dest: IInterface; const Source: IInterface; const IID: TGUID);
{$IF defined(PUREPASCAL) or defined(PIC)}
// PIC: EBX must be correct before calling QueryInterface
var
Temp: Pointer;
begin
if Source = nil then
Dest := nil
else
begin
Temp := nil;
if Source.QueryInterface(IID, IInterface(Temp)) <> 0 then
ErrorAt(byte(reIntfCastError), ReturnAddress)
else
begin
if Assigned(Dest) then
Dest._Release;
Pointer(Dest) := Temp;
end;
end;
end;