你为什么要用AS?一般说来,就是几个同一类型的控件对应一个共同的事件才用。如:Button1.OnClick:=ButtonClick;
Button1.Tag:=1;
Button2.OnClick:=ButtonClick;
Button2.Tag:=2;
Button3.OnClick:=ButtonClick;
Button3.Tag:=3;procedure TFormMain.ButtonClick(Sender: TObject);
begin
  ShowMessage('Button'+IntToStr((Sender as TButton).Tag));
end;

解决方案 »

  1.   


    这才像个技术问题!
    这样来回答吧:  获取接口指针有三种方法,一种是直接分配,一种是as操作符,最后一种——后面讲。(一)第一种,如(对上面有修改)MyClass: TMyClass;
    MyIntf: IMyInterface;MyClass:= TMyClass.Create(10); //必须有对象的实例
    MyIntf := MyClass as IMyInterface;但是,有时不知道对象是否支持某接口,容易产生错误,所以一般使用对象的GetInterface函数(该函数是TObject的成员函数),如:MyClass:= TMyClass.Create(10); 
    if MyClass.GetInterface(IMyInterface,MyIntf) then 
    begin
      //已经关联,MyIntf可以用了
      //该干什么干什么
    end;
    (二)使用as操作符(注:使用getInterface和as操作符的共同前提是——必须同时赋予一个GUID),如:MyClass:= TMyClass.Create(10); 
    MyIntf := MyObj as IMyInterface;使用as操作符,若对象不支持接口,会产生一个异常。而TObject.GetInterface不会。
    另一方面,GetInterface是TObject的成员函数,只能在对象上使用,而as还可以在接口本身中使用,如:procedure DoSomething(I:IUnkonw);
    var
      MyIntf:IMyInterface;
    begin
      (I as IMyInterface).Function; //Function指接口定义的某个函数
    end;
      而使用as会有一个副作用(也是上面出现问题的关键):使用as操作符,Delphi会调用_AddRef接口使用完成之后会调用_Release函数。
      而在使用完as操作符之后,若此时对象的引用计数为0,则该对象将被立刻销毁,如:
    begin  
      MyClass:= TMyClass.Create(10);   DoSomething(MyClass as IMyInterface);//此句执行完成后,对象已经被销毁  MyClass.Function; //此处再调用其方法将出现错误
    end;但如果上面的DoSomething是变参引用或常量引用,则上面引用代码将不会出错,譬如如下面声明:procedure DoSomething(var I:IUnkonw);

    procedure DoSomething(const I:IUnkonw);因为他们是引用地址传递而不是值传递(引用地址传递,Delphi将不会调用_AddRef、_Release方法)。(三)绕过自动计数(不推荐使用,因为他不属于规范的代码设计)就是将上面的对象强制增加引用计数:begin  
      MyClass:= TMyClass.Create(10);   MyClass._AddRef; //强制增加调用  DoSomething(MyClass as IMyInterface);//此句执行完成后,对象已经被销毁  MyClass.Function; //此处再调用其方法将出现错误  MyClass.Release; //恢复计数end;这样就不用去管DoSomething是如何声明的了!
    >>---------------------------------------------------------------(附注说明)以上内容看完后,相信你仍然会觉得很不可理解!你可能会认为:(问题一)MyClass:= TMyClass.Create(10); //我已经将初始化的引用计数设置为10,怎么还会出现对象被销毁的情况???这便是Delphi的精妙之处!他在你的程序中间添加了一层东西——智能指针!使程序员从烦琐、恐怖的构造代码中解放出来。
    Delphi中的智能指针是隐含编译的,这也是为什么你的接口引用代码为什么不用象C++中那样显式的调用_AddRef和_Release方法。不知道你是否对C++的智能指针有所了解?其实他相当于在接口和实现接口的对象实例中间添加了一层“安全引用计数”,是完全自动的。所以不管你设置对象实例的初始值是多少,都不会起作用!  C++中,Interface被简单定义为等同于Struct的宏,而在我看来,Delphi中的Interface绝不会是那样一个简单的宏定义,因为他至少在编译时包含了智能指针!
    (问题二)为什么将接口以值的形式传递给调用函数时可能会引发对象销毁?而使用var及const 不会?这就是接口规范!(设计规范,就是不要试图去改变的东西)接口规范包含数个部分,这里列出接口引用计数的规则:1、输入参数规则:对于传入函数的接口指针,无须调用AddRef和_Release。2、输出参数规则:任何输出参数中(或返回值)返回一个新的接口指针的函数都必须对此接口指针调用_AddRef,这条规则最经典的例子就是QueryInterface了!3、输入输出参数:对于输入输出参数传递进来的接口指针,必须在给它赋另外一个接口指针之前调用其_Release方法。在函数返回之前,还必须对输出参数中保存的接口指针调用AddRef。(我感觉C++的参数与Delphi中有一些微妙变化,自己去Discover吧!)
    清晨愉快!
      

  2.   

    接口引用计数的规则补充:4、局部变量规则:属于接口生命周期范围内,无须调用_AddRef及_Release。5、全局变量规则:对于保存在全局变量中的接口指针,将其传递给另外一个函数之前,必须调用_AddRef。而任何函数都可以调用_Release结束其生命周期。6、不确定时规则:任何不确定的情形,都应当调用_AddRef和_Release。Over!