以下代码不起作用。
program Project7;
{$APPTYPE CONSOLE}
{$R *.res}
uses System.SysUtils;
type
I1 = interface
['{B4BF44AD-23A9-4F42-BA2B-6E137E22344E}']
procedure Test1;
end;
I2 = interface(I1)
['{AAAAAAAA-23A9-4F42-BA2B-BBBBBBBBBBBB}']
procedure Test2;
end;
T12 = class(TInterfacedObject, I2)
public
procedure Test1;
procedure Test2;
public
function MeAsI1: I1;
function MeASI2: I2;
end;
function T12.MeAsI1: I1;
begin
Result:= (self as I1);
end;
function T12.MeASI2: I2;
begin
Result:= (self as I2);
end;
procedure T12.Test1;
begin
Writeln('T12: test1 from interface i1');
end;
procedure T12.Test2;
begin
Writeln('T12: test2 from interface i2');
end;
实行:
var
MyClass: T12;
AI1: I1;
AI2: I2;
begin
MyClass:= T12.Create;
AI2:= MyClass.MeAsI2;
AI2.Test2;
Readln;
AI1:= MyClass.MeAsI1; //<< Exception interface not supported
AI1.Test1;
Readln;
end.
它给出了一个例外:interface not supported
。
看起来interface inheritance
并不像class inheritance
那样真正起作用
如果我将接口I1
添加到类T12
它确实有效,但当类实现许多接口时,这会有点傻。
有没有办法只声明I2
并且仍然可以从班级内部返回对I1的引用?
我正在使用Delphi XE6,但我确信Delphi 3中的错误是相同的。
修改
一个用例是:
IReadOnly = interface
function GetSomething: integer;
...
IRWIntf = interface(IReadOnly)
procedure SetSomething(value: integer);
....
答案 0 :(得分:4)
这是设计的。您只能从类声明中明确提到的类中检索这些接口。
关于你的例子:由于I2是从I1继承而来的,你可以直接从AI2调用I1的方法,也可以在I1接口的任何地方传递AI2。
答案 1 :(得分:2)
接口继承遵循接口的逻辑。使用接口可以定义声明而无需任何实现。所以继承的接口只有相同的声明,因此没有实现继承。
但您可以执行以下操作
procedure UseI1( AI1 : I1 );
begin
AI1.Test1;
end;
procedure UseI2( AI2 : I2 );
begin
AI2.Test1;
AI2.Test2;
UseI1( AI2 ); // use the inherited interface
end;
如果您希望样本类输出I1
,则必须更改方法
function T12.MeAsI1: I1;
var
LI2 : I2;
begin
LI2 := Self;
Result := LI2;
end;
但你必须要小心。想想实现I1
和I2
TImplementor = class( TInterfacedPersistent, I1, I2 )
private
procedure I1_Test1;
procedure I2_Test1;
procedure I2_Test2;
procedure I1.Test1 = I1_Test1;
procedure I2.Test1 = I2_Test1;
procedure I2.Test2 = I2_Test2;
end;
procedure TImplementor.I1_Test1;
begin
Writeln( 'I1_Test1' );
end;
procedure TImplementor.I2_Test1;
begin
Writeln( 'I2_Test1' );
end;
procedure TImplementor.I2_Test2;
begin
Writeln( 'I2_Test2' );
end;
现在我们可以使用这个
var
LImplementor : TImplementor;
begin
LImplementor := TImplementor.Create;
try
UseI1( LImplementor );
// Output
// I1_Test1
UseI2( LImplementor );
// Output
// I2_Test1
// I2_Test2
// I2_Test1 !!!!!
finally
LImplementor.Free;
end;
end;
虽然我们两次调用UseI1
,但我们得到两个不同的输出,因为调用了两种不同的方法。