Board logo

Subject: TInterfaceObject的子类能否像TObject的子类一样使用? [Print This Page]

Author: Passion    Time: 2007-2-1 09:52     Subject: TInterfaceObject的子类能否像TObject的子类一样使用?

昨晚和zjy的讨论中说到这个问题的,没有确定答案,所以拿出来和大家讨论讨论:

讨论:《TInterfaceObject的子类,能否像TObject的子类一样使用?》

大家都知道,TInterfaceObject的子类创建的对象可以赋值给接口类型的变量,这个接口类型的变量还可以和其他接口类型的变量互相赋值,这种赋值在引用计数和自动释放等方面都没有问题。

但如果我们使用时不需要接口,那我们能否完全抛弃TInterfaceObject中的接口方面的内容,而把它当作一个TObject的子类来处理?

也就是说,对于TInterfaceObject的子类创建的对象,现在我们不把它赋值给接口类型的变量,而赋值给对象类型的变量,并且这些对象我们自己创建,自己手工释放。这种情况下,TInterfaceObject自身的引用计数机制,会不会对我们自己管理的创建、释放等造成影响?
Author: kendling    Time: 2007-2-1 09:55

没有玩过接口
Author: koalaone    Time: 2007-2-1 09:59

这个还没有玩过,有空可以玩下,BT一下
Author: crystal999    Time: 2007-2-1 10:18

TTrial = class(TInterfacedObject)
  constructor Create;
  destructor Destroy; override;
  end;
var
  Form1: TForm1;

implementation

{$R *.dfm}


procedure TForm1.btn1Click(Sender: TObject);
var
  T: IInterface;
begin
  T := TTrial.Create;
end;

{ TTrial }

constructor TTrial.Create;
begin
  inherited;
  ShowMessage('Create');
end;

destructor TTrial.Destroy;
begin
   ShowMessage('destroy');
  inherited;
end;

procedure TForm1.btn2Click(Sender: TObject);
var
  T: TTrial;
begin
  T := TTrial.Create;
end;
运行一下我得例子

[ 本帖最后由 crystal999 于 2007-2-1 10:37 编辑 ]
Author: jAmEs_    Time: 2007-2-1 10:31

我今天才知道IInterface会在作用域内自动释放的。。。这样安全吗?
Author: crystal999    Time: 2007-2-1 10:35

当然安全了
Author: Passion    Time: 2007-2-1 10:46

Interface本身安全,但如果和非Interface混用,就不那么安全了。
Author: jAmEs_    Time: 2007-2-1 11:38

那Delphi不是可以用这个东西来实现资源的自动释放?
不知道内部是怎么实现的?
Author: Passion    Time: 2007-2-1 11:57

就是编译器碰到interface类型的变量在使用和不用时,自动生成代码调它的_AddRef和_Release方法。
俩方法的实现由实现interface的类自己控制。
Author: Passion    Time: 2007-2-1 11:58

TInterfaceObject对_AddRef和_Release方法的实现就是:加一减一,到0就Free。
因此实现了接口的类如果是从TInterfaceObject继承下来的,则其接口引用计数可以自动处理自动释放。
Author: jAmEs_    Time: 2007-2-1 12:11

使用自然要知道很容易,但是不使用好像就挺困难的。
C++里面,类可以两种方式构造,一是变量形式,一是指针形式,变量形式可以自动释放,指针必须手工释放。比如类TTest可以
TTest t;
...
或者
TTest *pT = new TTest();
delete pT;
...
据我所知,第一种是编译的时候,C++编译器自动在作用域完毕前增加释放的代码。但是第二种要知道什么时候不使用比较困难的。而Delphi这个好像就是属于第二种了,所以不知道怎么实现的。简单的说,在作用域完毕前,接口肯定做了_Release,问题是在哪里做了?
至于接口释放大概原理还是知道的。
Author: Passion    Time: 2007-2-1 13:09

由于Delphi的对象本身都是引用,而对象存放在堆上,因此Delphi的接口使用,原理上是第二种。但在Pascal语法上看来,像第一种。
Delphi对这个原理上第二种但实现像第一种的处理的比较好。
但如果自己加入指针机制,比如取到一个接口变量的地址,然后用指针把内容复制过去等,这种情况编译器应该同样也处理不了。
Author: shenloqi    Time: 2007-2-1 13:29

只要不混用就没有什么问题,一旦混用就要注意成为接口之后就不要再把接口指针强制转换为对象,否则很容易出问题。

如果需要混用且需要自己来处理对象的创建和释放,则可以需要使用TInterfacedPersistent。

关于自己的引用计数与生命周期的管理的主要原则就是自动管理引用计数的接口对象可以当作接口用,可是一旦成了接口之后就不要再当作对象了(比如创建了,然后作为接口使用了,最后就不应该自己Free,否则会出错),如果需要从接口返回对象,则需要从TInterfacedPersistent继承(不使用自动引用计数)或者是实现一个可以获得对象的接口,如下:

IAsObject = interface
[IID]
  function AsObject: TObject;
end;

然后需要使用的类实现IAsObject和其他的接口,要返回对象本身是就使用AsObject。
Author: jAmEs_    Time: 2007-2-1 14:28



QUOTE:
原帖由 Passion 于 2007-2-1 13:09 发表
由于Delphi的对象本身都是引用,而对象存放在堆上,因此Delphi的接口使用,原理上是第二种。但在Pascal语法上看来,像第一种。
Delphi对这个原理上第二种但实现像第一种的处理的比较好。
但如果自己加入指针机制,比如取到一个 ...

其实是不是可以说,应该无论哪种语言自动释放的,应该都只是编译器在作用罢了?
Author: jAmEs_    Time: 2007-2-1 14:30

不过我讨论这个是想看看Delphi下有没有方便实现自动释放指针的方法,就像C++下面的SmartPtr。如果是编译器在作用,也就没有可以代码实现的,只能依赖编译器了。
Author: jAmEs_    Time: 2007-2-1 18:00

好像不是很安全。。。迟点再看看。。。
http://www.mx68.com/WebDeveloper ... veloper_23880.shtml
Author: Passion    Time: 2007-2-1 18:21

那篇文章自己把接口和对象混用,出了问题说接口不安全。最后还建议全用Pointer方式来处理,实在是误导。
接口是有局限性,但也不是这么一乱用就能说有大问题的吧。
Author: jAmEs_    Time: 2007-2-2 09:35

还没认真阅读,不过有些地方好像的确是说的不对。




Welcome to CnPack Forum (http://bbs.cnpack.org/) Powered by Discuz! 5.0.0