Delphi Interface 中的函数(200分)

  • 主题发起人 主题发起人 larryle
  • 开始时间 开始时间
L

larryle

Unregistered / Unconfirmed
GUEST, unregistred user!
编译下面代码的时候总是告诉我'Not enough actual parameters',就在
btnClose.onClick=listener.onNotifyEvent 这句这出错。
如果把 setListener(listener: IEventListener);改为
TForm1.setListener(listener: TControll);就没错。
我理解,问题可能出在TNotifyEvent的定义上,interface的函数和class中的函数即使定义完全一样,delphi也认为是不同的。
哪位能给个主意,使编译的时候不出错误(listener 类型还是IeventListener)?

谢谢

larry


=================================================================
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
IEventListener = interface
procedure onNotifyEvent(Sender: TObject);
end;

TControll = class(TInterfacedObject, IEventListener)
procedure onNotifyEvent(Sender: TObject);
end;

TForm1 = class(TForm)
btnClose: TButton;
private
{ Private declarations }
public
{ Public declarations }
procedure setListener(listener: IEventListener);
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TControll.onNotifyEvent(Sender: TObject);
begin
if TButton(sender).caption = 'Close' then

else
end;


procedure TForm1.setListener(listener: IEventListener);
begin
btnClose.onClick := listener.onNotifyEvent
// 这出错
end;

end.
 
我记得所有类的方法都隐含带有一个Self的参数,这个是要压栈的 ,而接口没有Self这个指针吧.所以报告实际参数不对的错误.
 
接口本身就是指针,怎么还要Self指针呢?
btnClose.OnClick本身隐藏了btnClose.OnClick(self),转入到接口声明中,接口不存在Self指针。。
也就说,接口只是声明,真正的调用和转换必须通过类实现,你已经申明了类TControll就用它就是了。
感觉应该改为:
procedure setListener(listener: IEventListener);
改为:
procedure setListener(listener: TControll);
btnClose.onClick := listener.onNotifyEvent;
通过了。。使用接口的时候,任何情况下都是用的类,哪怕使用Variant也好,也要创建类,没有类,就引用接口接口也就无法使用。。
这里的原因是怎么传递这个类实例。。。。


我认为。。。见笑。。
 
注意,我说的Self是隐含的,是Object Pascal规范定义的,Sender可以传一个Self作为对象(好比这句:btnClose.OnClick([red]self[/red])),可这个Self怎么来的呢?我是说红色本身哪里来的?怎么确定的?凡是不属于类的方法,都不能写self这个字,因为没有传进来这个隐含参数!!!

[转载内容]出处:http://delphi.apub.org/doc/2006/07/12/10/21/53/166671.html

tungco (2001-03-04 20:07:00)
TNotifyEvent 是这样定义的:
TNotifyEvent=procedure (sender:TObject) of object
请问,这个TNotifyEvent到底是个什么?类?方法?还是其他什么类型?其中的
of object是什么意思?这种定义是object pascal语言的还是delphi的?



douh (2001-03-04 22:56:00)
是object pascal语言的过程类型的一种,of object 表明它必须是一个方法,换句话说
调用这个过程时,在将参数入栈后,先(隐含地)入栈一个对象的32位(Self)指针,
做为参数表的最后一个参数。再调用这个方法的指针,方法过程类型的指针必须是一个长
指针(含段及偏移)。

而普通的过程类型在被调用时就没有这个Self参数。过程指针有长有短,在interface部份
声明过的就是长指针,否则是短指针。
 
zqw0117,有理,收藏了。
 
Delphi中的事件实际上是方法指针,它要求一个对象的某个方法.
Delphi里只有 procedure of Object 的语法,而没有 procedure of interface.
所以你的代码错了.
 
listener定義的是什麼東西,如果是類就沒有問題,如果是接口,肯定不行,沒有辦法的;
還有感覺你的代碼有點繞彎子.
 
谢谢诸位的答复,其实我的本意是这样的
定义IEventListener接口,用于截获所有form中按钮的onClick事件。
TControll类实现IEventListener接口,根据不同按钮事件,做不同运算。
之所以引入IEventListener,就是不想让FORM与TControll类发生任何直接耦合。
即Form 不知道具体是哪个类控制它,它只针对IEventListener接口。

我知道有绕弯的办法
比如在form中声明一个私有变量
iListener:IEventListener;
和一个函数
procedure MyClick(Sender:TObject).

函数内容如下
procedure TForm1.MyClick(Sender:TObject).
begin
if assigned(iListener) then
iListener.OnNotifyEvent(Sender);
end;

然后更改
procedure setListener(listener: IEventListener);
begin
iListener := Listener;
end;

在Form的Create函数中把所有button.OnClick := self.MyClick;

这招肯定行,但是有点麻烦,而且显得业余。我要的是能够一条赋值语句就解决问题。
不知道哪位能够给点思路。如果有解,这200分不算,我再出1000分。
 
Delphi 的事件处理机制已经够简单的了,你想模拟java的方式?
 
Delphi在事件设计的时候就隐藏了Self这个指针,所以要想编译通过,必须用类。
完全可以把TControll做成虚类,实现方法有子类控制好了。
 
to xeen: yes, 我是想模拟java的事件处理机制
To sundayboys:你的主意不错,但如果用接口能做到,我还是比较偏向用接口。
 
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
IEventListener = interface
procedure onNotifyEvent(Sender: TObject);
end;

TControll = class(TInterfacedObject, IEventListener)
procedure onNotifyEvent(Sender: TObject);
end;

TForm1 = class(TForm, IEventListener)
Button1: TButton;
Button2: TButton;
procedure FormCreate(Sender: TObject);
private
FEventListener: IEventListener;
procedure EventListenerNotify(Sender: TObject);
public
property EventListener: IEventListener read FEventListener write FEventListener
implements IEventListener;
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TControll.onNotifyEvent(Sender: TObject);
begin
ShowMessage('Controll Notify');
end;

procedure TForm1.EventListenerNotify(Sender: TObject);
begin
if Assigned(FEventListener) then
FEventListener.onNotifyEvent(Sender);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
FEventListener := TControll.Create;
Button1.OnClick := EventListenerNotify;
end;

end.
 
虽然没有得到我想要的答案,但是还是非常感谢大家,谢谢。
另外,我承诺的1000分仍然有效,希望谁能够给出一个满意的答案。谢谢
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
541
import
I
I
回复
0
查看
686
import
I
I
回复
0
查看
763
import
I
后退
顶部