2011-12-11 22 views
18

¿Cuál es la razón por la que esto no se compilará?Cuando una clase implementa una interfaz descendiente, ¿por qué no cuenta automáticamente como implementar la interfaz base?

type 
    IInterfaceA = interface ['{44F93616-0161-4912-9D63-3E8AA140CA0D}'] 
    procedure DoA; 
    end; 

    IInterfaceB = interface(IInterfaceA) ['{80CB6D35-E12F-462A-AAA9-E7C0F6FE0982}'] 
    procedure DoB; 
    end; 

    TImplementsAB = class(TSingletonImplementation, IInterfaceB) 
    procedure DoA; 
    procedure DoB; 
    end; 

var 
    ImplementsAB: TImplementsAB; 
    InterfaceA: IInterfaceA; 
    InterfaceB: IInterfaceB; 
begin 
    ImplementsAB := TImplementsAB.Create; 
    InterfaceA := ImplementsAB; >> incompatible types 
    ... 
end 

En contraste Éste es cómo hacer que funcione:

InterfaceA := ImplementsAB as InterfaceB; 

o

InterfaceA := InterfaceB; 

Es decir, si IInterfaceB hereda de IInterfaceA y TImplementsAB implementa IInterfaceB, no sería lógico para también implementar IInterfaceA y ser compatible con el tipo?

Respuesta

27

Esto es así porque los primeros OLE/COM tenían un error y Borland decidió ser compatible con él. Esto se menciona en este artículo: New Delphi language feature: Multiple inheritance for interfaces in Delphi for .NET. La solución es listar explícitamente todas las interfaces de ancestros en la clase como escribió Mikael.

algunas citas del artículo enlazado:

El problema era en sí mismo COM. Para cargar un módulo, COM cargaría la DLL, GetProcAddress en un punto de entrada conocido que se suponía que se exportaría de la DLL, llamaría a la función DLL para obtener una interfaz IUnknown, y luego a QueryInterface para IClassFactory. El problema era que cuando Microsoft agregó soporte para IClassFactory2, agregaron QueryInterface para IClassFactory2 después del código existente que consultaba por IClassFactory. IClassFactory2 solo se solicitaría si la consulta de IClassFactory fallara.

Por lo tanto, COM nunca solicitaría IClassFactory2 en ningún servidor COM que implementara tanto IClassFactory2 como IClassFactory.

Este error existía en COM desde hace mucho tiempo. Microsoft dijo que no podían reparar el cargador COM con un paquete de servicio del sistema operativo porque tanto Word como Excel (en ese momento) confiaban en el comportamiento de los errores. Independientemente de si se ha solucionado en las últimas versiones de COM o no, Borland tiene que proporcionar alguna forma de preservar este comportamiento en Win32 Delphi para el futuro previsible. De repente, agregar todos los antepasados ​​a una clase de implementación que no estaban allí antes es muy probable que rompa el código existente que involuntariamente caiga en el mismo patrón que el cargador COM.

+6

+1 No sabía la razón, ¡gracias! –

+1

+1 de mí también. –

+0

¿Qué "error" temprano de OLE/COM? –

6

Otra forma de hacerlo funcionar es incluir ambas interfaces en la declaración de clase.

TImplementsAB = class(TSingletonImplementation, IInterfaceA, IInterfaceB) 
    procedure DoA; 
    procedure DoB; 
end; 

supongo que esto es lo que se requiere para que el compilador se da cuenta de que TImplementsAB implementa tanto IInterfaceA y IInterfaceB.

Cuestiones relacionadas