Delphi的Interface要怎麼用? |
尚未結案
|
jeffxx
一般會員 發表:7 回覆:22 積分:5 註冊:2003-10-10 發送簡訊給我 |
(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 發送簡訊給我 |
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 發送簡訊給我 |
第一、第二個問題我大概懂了~ 第三個問題我的重點是在
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 發送簡訊給我 |
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 發送簡訊給我 |
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 發送簡訊給我 |
這樣如何,
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 發送簡訊給我 |
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 發送簡訊給我 |
|
malanlk
尊榮會員 發表:20 回覆:694 積分:577 註冊:2004-04-19 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |