全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:2114
推到 Plurk!
推到 Facebook!

Delphi的Interface要怎麼用?

尚未結案
jeffxx
一般會員


發表:7
回覆:22
積分:5
註冊:2003-10-10

發送簡訊給我
#1 引用回覆 回覆 發表時間:2005-07-28 16:53:18 IP:61.222.xxx.xxx 未訂閱
(1)請問delphi的interface只能宣告不能實作(跟java的一樣)嗎? (2)為什麼我繼承interface他要叫我實作 function Queryinterface(const IID: TGUID; out Obj): HResult; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; 如果不實作會怎樣?如果不想要的話要怎麼宣告 (3) //============================================================ type IMyInterface = interface procedure play; end; TMyGame = class(TObject, IMyInterface) function Queryinterface(const IID: TGUID; out Obj): HResult; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; procedure play; end; TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} { TMyGame } procedure TMyGame.play; begin showmessage('play my game'); end; function TMyGame._AddRef: Integer; begin end; function TMyGame._Release: Integer; begin end; function TMyGame.Queryinterface(const IID: TGUID; out Obj): HResult; begin end; procedure TForm1.Button1Click(Sender: TObject); var MyInterface: IMyInterface; collect: TStringList; tmp: TObject; begin collect := TStringList.Create; collect.AddObject('', TMyGame.Create); tmp := collect.Objects[0]; MyInterface := (tmp as TMyGame); MyInterface.play; collect.free; end; end. //================================================================ 程式中MyInterface := (tmp as TMyGame);為什麼不能寫(tmp as IMyInterface) 如果我只關心取回來物件的方法而不想指定類別可以嗎? 謝謝 發表人 - jeffxx 於 2005/07/28 17:06:51
malanlk
尊榮會員


發表:20
回覆:694
積分:577
註冊:2004-04-19

發送簡訊給我
#2 引用回覆 回覆 發表時間:2005-07-28 19:06:32 IP:203.69.xxx.xxx 未訂閱
COM 介面的目的是要在兩個模組, 兩個可執行檔, 或 ㄧ個執行檔ㄧ個dll 間作溝通, 因此要有一定的規範, 而 實作 IUnknown 介面就是規範之一, IUnknown 有三個方法就是 Queryinterface, AddRef, Release. 在 System.pas 可以找到定義, AddRef, Release 是實作 reference counting, 而 Queryinterface則用來處理物件的型別資訊及型別相容性. 基本上 delphi 已經提供有實作的類別 TComObject, 已經有實作 IUnknown 介面(ComObj.pas) 所以你的問題 1. 你宣告 interface 時並沒有繼承任何東西, 而只是宣告你的東西是一種自訂的溝通介面 2.因為每個COM 物件都必須提供 IUnknown 介面, 這跟你宣告的 interface 無關, 而是因為你做的是 COM 物件, 你宣告的 interface 只是你物件的介面之一. 如果不實作就不符 COM 規範. 3. 如果不想作 就讓你的物件繼承 TComObject TMyComObj = class(TComObject, IMyInterface) ......
jeffxx
一般會員


發表:7
回覆:22
積分:5
註冊:2003-10-10

發送簡訊給我
#3 引用回覆 回覆 發表時間:2005-07-28 22:44:36 IP:220.135.xxx.xxx 未訂閱
第一、第二個問題我大概懂了~ 第三個問題我的重點是在 procedure TForm1.Button1Click(Sender: TObject); var MyInterface: IMyInterface; collect: TStringList; tmp: TObject; begin collect := TStringList.Create; collect.AddObject('', TMyGame.Create); tmp := collect.Objects[0]; MyInterface := (tmp as TMyGame);//把物件的ref assign 給 interface的ref //=>我想問的是上面這句 //我主要的目是我可能有不同的實作都叫play (implements IMyInterface ) //但只要能play的話我就把它動態create起來丟到collect //然後在某個事件下全部取出來執行(tmp as IMyInterface).play <=為什麼這句錯 MyInterface.play; collect.free; end; //================================================================ 程式中MyInterface := (tmp as TMyGame);為什麼不能寫(tmp as IMyInterface) 如果我只關心取回來物件的"方法"而不想"指定類別"可以嗎?
malanlk
尊榮會員


發表:20
回覆:694
積分:577
註冊:2004-04-19

發送簡訊給我
#4 引用回覆 回覆 發表時間:2005-07-29 00:45:47 IP:61.219.xxx.xxx 未訂閱
MyInterface := (tmp as TMyGame); 為什麼不能寫(tmp as IMyInterface)    因為 tmp 是個 TObject 類別, 並不是 interface. 其實 MyInterface := (tmp as TMyGame); 就是   MyInterface := IMyInterface(tmp as TMyGame);    已經達到你取得 MyGame 的 IMyInterface 的目的了    這支程式離完全可執行還有一段距離, 可是你的觀念應該沒錯.    
unit Unit1;    interface    uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComObj, Contnrs;    type    IMyInterface = interface
  procedure play;
end;    TMyGame = class(TComObject, IMyInterface)       procedure play;    end;    type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;    var
  Form1: TForm1;    implementation    {$R *.dfm}    { TMyGame }    procedure TMyGame.play;
begin
  showmessage('play my game');
end;    procedure TForm1.Button1Click(Sender: TObject);
var
  MyInterface: IMyInterface;
  collect: TObjectList;
  tmp: TObject;
begin
  collect := TObjectList.Create;
  collect.Add(TMyGame.Create);      tmp := collect.Items[0];
  //MyInterface := (tmp as TMyGame);
  MyInterface := IMyInterface(tmp as TMyGame);
  MyInterface.play;
  
  TMyGame(tmp).free;
  collect.free;
end;    end.
jeffxx
一般會員


發表:7
回覆:22
積分:5
註冊:2003-10-10

發送簡訊給我
#5 引用回覆 回覆 發表時間:2005-07-29 07:39:16 IP:220.135.xxx.xxx 未訂閱
sorry 我不太會問問題我再寫仔細一點 (1)實作兩類別具同樣介面 //定義介面 IMyInterface = interface procedure play; end; //實作介面一 TMyGame = class(TObject, IMyInterface) function Queryinterface(const IID: TGUID; out Obj): HResult; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; procedure play; end; //實作介面二 TJeffGame = class(TObject, IMyInterface) function Queryinterface(const IID: TGUID; out Obj): HResult; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; procedure play; end; procedure TMyGame.play; begin showmessage('play my game'); end; procedure TJeffGame.play; begin showmessage('play jeff game'); end; (2)事件 procedure TForm1.Button1Click(Sender: TObject); var MyInterface: IMyInterface; collect: TStringList; tmp: TObject; i: Integer; begin collect := TStringList.Create; collect.AddObject('', TMyGame.Create); collect.AddObject('', TJeffGame.Create); for i := 0 to collect.Count - 1 do begin tmp := collect.Objects[i]; //=========以類別來判斷 這是可行的但新增類別就要修改程式==========// if tmp is TMyGame then begin (tmp as TMyGame).play; end; if tmp is TJeffGame then begin (tmp as TJeffGame).play; end; //********我主要的問題在這裡 //========以介面來判斷 這是錯的可以有語法寫出以下的功能嗎============// // 目的:當我新增類別時只要implements IMyInterface // 就可以參與這個事件不用為新增的類別修改程式碼 // if tmp is IMyInterface then // begin // MyInterface := (tmp as IMyInterface); // MyInterface.play; // end; end; collect.Free; end;
malanlk
尊榮會員


發表:20
回覆:694
積分:577
註冊:2004-04-19

發送簡訊給我
#6 引用回覆 回覆 發表時間:2005-07-29 08:52:33 IP:203.69.xxx.xxx 未訂閱
這樣如何,    
unit Unit1;    interface    uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComObj, Contnrs;    type    IMyInterface = interface
  procedure play;
end;    TMyGame = class(TComObject, IMyInterface)
  procedure IMyInterface.play=playGame;
  procedure playGame;
end;    TMyJeffGame = class(TMyGame)
   // this is Game Created by jeff
  procedure playGame;
end;    TMyMalanlkGame = class(TMyGame)
   // this is Game Created by malanlk
  procedure playGame;
end;    type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;    var
  Form1: TForm1;    implementation    {$R *.dfm}    { TMyGame }    procedure TMyGame.playGame;
begin
  showmessage('play my game');
end;    procedure TMyJeffGame.playGame;
begin
  showmessage('play my Jeff game');
end;    procedure TMyMalanlkGame.playGame;
begin
  showmessage('play my Malanlk game');
end;    procedure TForm1.Button1Click(Sender: TObject);
var
  collect: TObjectList;
  tmp: TMyGame;
begin
  collect := TObjectList.Create;
  collect.Add(TMyJeffGame.Create);
  collect.Add(TMyMalanlkGame.Create);      tmp := TMyGame(collect.Items[0]);
  IMyInterface(tmp).play;
  tmp.free;      tmp := TMyGame(collect.Items[1]);
  IMyInterface(tmp).play;
  tmp.free;      collect.free;
end;    end.
malanlk
尊榮會員


發表:20
回覆:694
積分:577
註冊:2004-04-19

發送簡訊給我
#7 引用回覆 回覆 發表時間:2005-07-29 09:18:52 IP:203.69.xxx.xxx 未訂閱
Sorry, 我不應該一直執著於要做出ㄧ個 COM 物件, 其實下列程式就可以執行了    
unit Unit2;    interface    uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Contnrs;    type    IMyInterface = interface
  procedure play;
end;    TMyGame = class(TObject, IMyInterface)
  procedure IMyInterface.play=playGame;
  procedure playGame; virtual; abstract;
  function Queryinterface(const IID: TGUID; out Obj): HResult; stdcall;
  function _AddRef: Integer; stdcall;
  function _Release: Integer; stdcall;
end;    TMyJeffGame = class(TMyGame)
   // this is Game Created by jeff
  procedure playGame; override;
end;    TMyMalanlkGame = class(TMyGame)
   // this is Game Created by malanlk
  procedure playGame; override;
end;    type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;    var
  Form1: TForm1;    implementation    {$R *.dfm}    { TMyGame }    function TMyGame._AddRef: Integer;
begin
end;    function TMyGame._Release: Integer;
begin
end;    function TMyGame.Queryinterface(const IID: TGUID; out Obj): HResult;
begin
end;    procedure TMyJeffGame.playGame;
begin
  showmessage('play my Jeff game');
end;    procedure TMyMalanlkGame.playGame;
begin
  showmessage('play my Malanlk game');
end;    procedure TForm1.Button1Click(Sender: TObject);
var
  collect: TObjectList;
  i: Integer;
begin
  collect := TObjectList.Create;
  collect.Add(TMyJeffGame.Create);
  collect.Add(TMyMalanlkGame.Create);      for i:=0 to collect.Count-1 do
    IMyInterface(TMyGame(collect.Items[i])).play;      collect.free;
end;    end.
不用 interface 其實也是可以做的
unit Unit3;    interface    uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Contnrs;    type    TMyGame = class(TObject)
  procedure playGame; virtual; abstract;
end;    TMyJeffGame = class(TMyGame)
   // this is Game Created by jeff
  procedure playGame; override;
end;    TMyMalanlkGame = class(TMyGame)
   // this is Game Created by malanlk
  procedure playGame; override;
end;    type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;    var
  Form1: TForm1;    implementation    {$R *.dfm}    { TMyGame }    procedure TMyJeffGame.playGame;
begin
  showmessage('play my Jeff game');
end;    procedure TMyMalanlkGame.playGame;
begin
  showmessage('play my Malanlk game');
end;    procedure TForm1.Button1Click(Sender: TObject);
var
  collect: TObjectList;
  i: Integer;
begin
  collect := TObjectList.Create;
  collect.Add(TMyJeffGame.Create);
  collect.Add(TMyMalanlkGame.Create);      for i:=0 to collect.Count-1 do
    TMyGame(collect.Items[i]).playGame;      collect.free;
end;    end.
發表人 - malanlk 於 2005/07/29 09:25:14 發表人 - malanlk 於 2005/07/29 09:27:41
jeffxx
一般會員


發表:7
回覆:22
積分:5
註冊:2003-10-10

發送簡訊給我
#8 引用回覆 回覆 發表時間:2005-07-29 09:56:57 IP:61.222.xxx.xxx 未訂閱
感謝malanlk大大解答疑惑 用interface原因是我以為interface是方法的集合 發表人 - jeffxx 於 2005/07/29 10:07:27
malanlk
尊榮會員


發表:20
回覆:694
積分:577
註冊:2004-04-19

發送簡訊給我
#9 引用回覆 回覆 發表時間:2005-07-29 10:47:10 IP:203.69.xxx.xxx 未訂閱
你沒錯, 就觀念而言 interface 確實是方法的集合, 但是通常是給 COM 用
系統時間:2024-04-26 8:39:08
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!