既不是调用MyObj.Free,也不是MyObj.Release;
破坏对象的正确方法是将它们设置为nil:
MyInterface := nil;
一个接口不能离开实现它的对象而独立存活。这个接口仅仅是一个抽象,它仅仅是一个想法。
接口具有即插即用的功能,它建立了供应商必须遵守的规范。
接口可以仅仅在一层深度上运行,比较简单。不像OOP,一层套一层,一旦改了中间层,即容易引起更下层的错误。
在本质上,接口并不鼓励创建深分层结构,而鼓励相对简单的具有较好的性能特征的程序。
GUID是128位的数字(16个字节),在统计上是唯一的。
为了产生自己的GUID,必须首先调用WINAPI函数CoInitialize来初始化,然后调用CoCreateGuid得到唯一的实例:
CoInitialize(nil);
CoCreateGuid(FGUID);
在32位的Windows中,除了向CoInitialize传递nil之外的任何东西都是错误的。
就COM对象而言,注册表是一个简单的数据库,它只有一个任务:把一个数字值与系统中每一个可用的COM对象联系起来。
这些值存放在HKEY_CLASSES_ROOT的CLSID
注册表是一个数据库,它会建立CLSID与程序的名字以及其它相关信息之间的关联,例如版本号和文件的存储位置。
微软白送几个API
function StringFromCLSID; external ole32 name ‘StringFromCLSID‘;
function CLSIDFromString; external ole32 name ‘CLSIDFromString‘;
function StringFromIID; external ole32 name ‘StringFromIID‘;
function IIDFromString; external ole32 name ‘IIDFromString‘;
function ProgIDFromCLSID; external ole32 name ‘ProgIDFromCLSID‘;
function CLSIDFromProgID; external ole32 name ‘CLSIDFromProgID‘;
function StringFromGUID2; external ole32 name ‘StringFromGUID2‘;
function CoCreateGuid; external ole32 name ‘CoCreateGuid‘;
另外还有几个常见的:
function CoInitialize; external ole32 name ‘CoInitialize‘;
function CoInitializeEx; external ole32 name ‘CoInitializeEx‘;
procedure CoUninitialize; external ole32 name ‘CoUninitialize‘;
function CoGetCurrentProcess; external ole32 name ‘CoGetCurrentProcess‘;
function CoGetClassObject; external ole32 name ‘CoGetClassObject‘;
function CoRegisterClassObject; external ole32 name ‘CoRegisterClassObject‘;
function CoLoadLibrary; external ole32 name ‘CoLoadLibrary‘;
procedure CoFreeLibrary; external ole32 name ‘CoFreeLibrary‘;
最有趣的事情是自己实现IUnknown:
function TUserUnknown.QueryInterface(const IID: TGUID; out Obj): HResult;
const
E_NOINTERFACE = $80004002
begin
// GetInterface是TOjbect的方法。也可这样写:Obj:=Pointer(Self);
// GetInterface用奇妙的方法返回一个小型VMT,它只包含用户需要的接口的方法,而只把Self作为一个可以返回对象中的所有方法的指针
if GetInterface(IID, obj) then result :=0;
else reslut := E_NOINTERFACE;
end;
function TUserUnknown._AddRef : integer;
begin
Inc(FRefCount);
Result := FRefCount;
end;
function TUserUnknown._Release: Integer;
begin
Dec(FRefCount);
Result := FRefCount;
if Result = 0 then Destroy;
end;
为指定接口加上GUID
IName = interface(IUnknown)
[‘{C25A86F1-579A-419A-8CB1-D1B5C6BCB8CB}‘]
function GetName : String;
end;
它的优越性在于,它允许你在需要在程序中使用GUID的时候,只需说明一个类名称就可以了。
例如,现在你知道这调用QueryInterface的时候,必须在第一个参数中传递一个GUID,方法只是编写如下代码:
var
Unknown : IUnknown;
Name : IName;
begin
FName.QueryInterface(IUnknown, Unknown);
FName.QueryInterface(IName, Name);
end;
Delphi接口编程比标准Delphi面向对象的编程更为简单,原因是不必为销毁对象而烦恼,一般它将被自动销毁。
参考:《Delphi4 编程技术内幕》第13章