接口和实现接口的类之间的转换

wolfpk 2004-09-11 10:43:58
//接口定义
IFirst =interface
function createNew():IFirst;
function readName():string;
procedure setValue(strValue:string);
end;

//接口实现类
TFirst=class(TInterfacedObject,IFirst)
public
strName:string;

function readName():string;
procedure setValue(strValue:string);
function createNew():IFirst;
end;

//接口类实现
function TFirse.readName():string;
begin
Result:=strName;
end;

function TFirst.setValue(strValue:string);
begin
strName:=strValue;
end;

function TFirst.createNew():IFirst;
begin
Result:=TFirst.create;
end;

//假设有一个方法
function doit(aIFirst:IFirst):IFirst;
begin
Result:=aIFirst.createNew;
Result.setValue('My Name');
end;

下面是调用
var
aTFirst:TFirst;
str:string;
begin
aTFirst:=TFirst.Create;
aTFirst:=TFirst(doit(aTFirst));//没出错;
str:=aTFirst.strName;//出错了;
aTFirst.Free;
end;

为什么??
...全文
257 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
苏丹-陈 2004-09-23
  • 打赏
  • 举报
回复
我也碰到这个问题,为什么要用接口是因为实现的类很多,Delphi又不能 A uses B
B uses A,所以定义一个unit,包含所有interface。其它unit都直接引用 这个unit
想在具体使用时,强制转换回类变量。但是现在就遇到这个问题了。
不知道大家有什么 好的解决方法没有! 非常感谢。
wolfpk 2004-09-12
  • 打赏
  • 举报
回复
也许我的例子太简单了
再详细些

//接口定义
IFirst =interface
function createNew():IFirst;
procedure setValue(aDataSet:TDataSet);
end;

//接口实现类
TFirst=class(TInterfacedObject,IFirst)
public
strName:string;
strData:string;//我的数据

procedure setValue(aDataSet:TDataSet);
function createNew():IFirst;
end;

//接口类实现
procedure TFirst.setValue(aDataSet:TDataSet);
begin
strName:=aDataSet.FieldValues['Name'];
strData:=aDataSet.FieldValues['Data'];
end;

function TFirst.createNew():IFirst;
begin
Result:=TFirst.create;
end;

//假设有一个方法,用于从数据库读取数据
function doit(aIFirst:IFirst):IFirst;
var
aDataSet:TDataSet;
begin
Result:=aIFirst.createNew;
//从数据库取得aDataSet的数据.....
Result.setValue(aDataSet);
end;

下面是调用
var
aTFirst:TFirst;
str:string;
strMyData:string;
begin
aTFirst:=TFirst.Create;
aTFirst:=TFirst(doit(aTFirst));//没出错;
str:=aTFirst.strName;//出错了;
strMyData:=aTFirst.strData;
aTFirst.Free;
end;


halfdream 2004-09-12
  • 打赏
  • 举报
回复
上面说的,可能不够清楚..我举一个较简单的例子..

Ixxxx=interface
procedure hello;
end;

Txxxx=class(TInterfacedObject,Ixxxx)
public
procedure hello;
end;


procedure p1;
var
a:Txxxx;
begin
a:=Txxxx.create;
a.hello;
end;//这个过程执行完后,对象a还存在内存中,不会销毁.


//这个现象比较有趣,但是很合情合理.

procedure p2;
var
a:Txxx;
b:Ixxx;
begin
a:=Txxx.create;
a.hello;
b:=a; //
end; //函数执行完后,变量b的内存是在堆栈中,它会释放,造成对象a引用计数为0,
//对象a被释放.




halfdream 2004-09-12
  • 打赏
  • 举报
回复
下面是调用
var
aTFirst:TFirst;
str:string;
strMyData:string;
begin
aTFirst:=TFirst.Create;
aTFirst:=TFirst(doit(aTFirst));//没出错;
//你这步,实际上是将IFirst类型强制转成TFirst,尽管不太安全,也还是可以的..
//留意你的doit,传参数进去的时候,对象被赋给了一个接口引用,
//当DoIt调用完后,对象的接口引用又被除去,这时候,对象引用计数为0,
//它自己就会被释放掉..

str:=aTFirst.strName;//出错了;
//这时候,对象已经被释放了,使用它当然会出错.
strMyData:=aTFirst.strData;
aTFirst.Free;
end;
linzhisong 2004-09-12
  • 打赏
  • 举报
回复
iFirst 没有这个StrName 变量。

你把他用First强制转化所以编译器不会提示。 但运行会出错的。

var c:TComponent;
begin
c:= TComponent.Create(nil);
TEDIT(c).Text := 'll';//也会出错
c.free;
end;

var c:TControl;
begin
c:= TControl.Create(nil);
TEDIT(c).Text := 'll';//就运行正常
c.free;
end;
wolfpk 2004-09-12
  • 打赏
  • 举报
回复
谢谢大家
wolfpk 2004-09-12
  • 打赏
  • 举报
回复
真没想到我没用as转换,这样还是会销毁掉它,我再想想办法吧
散分
linzhengqun 2004-09-11
  • 打赏
  • 举报
回复
好乱,用这样不就行了吗:
procedure TForm1.Button1Click(Sender: TObject);
var
aTFirst:IFirst;
str:string;
begin
aTFirst:=TFirst.Create;
aTFirst:=aTFirst.CreateNew;
aTFirst.setValue('my name');
Edit1.Text:= aTFirst.readName;
//Edit1.Text:=doit(aTFirst).strName;//出错了;
aTFirst:=nil;
end;
wolfpk 2004-09-11
  • 打赏
  • 举报
回复
噢。它应该是个TFirst的对象吧。难道TFirst转换为IFirst,就转换不回来了?
SuanAddMiao 2004-09-11
  • 打赏
  • 举报
回复
doit(aIFirst:IFirst)返回的是IFirst,能用吗?
wolfpk 2004-09-11
  • 打赏
  • 举报
回复
大家都睡了么。。。。

16,748

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧