我有一个继承自另一个接口的接口,如下所示:
[
object,
uuid(72A6E473-9956-4856-A335-B9169359AACE),
dual,
nonextensible,
pointer_default(unique)
]
interface IA : IDispatch
{
HRESULT MethodA();
}
[
object,
uuid(378846D3-7E24-4DAE-B4DF-69AA4B0C1AA9),
dual,
nonextensible,
pointer_default(unique)
]
interface IB : IA
{
HRESULT MethodB();
}
[
object,
uuid(4C187526-6809-4A57-A3ED-626E0B36F7DB),
dual,
nonextensible,
pointer_default(unique)
]
interface ICollection : IDispatch
{
HRESULT GetObject([out, retval] IA** ppValue);
}
ICollection实现将返回一个实现IB的对象。 该对象将通过调度接口提供对MethodA和MethodB的访问。 在运行时不会添加其他成员。
在这种情况下是否允许IA上的不可扩展属性?
答案 0 :(得分:1)
在这种情况下是否允许IA上的不可扩展属性?
是的,是的。
转换为typelib类型标志[nonextensible]
的接口的TYPEFLAG_FNONEXTENSIBLE
属性具有告诉Visual Basic(6或for Application)不查找具有基础{的缺少成员的实际效果。 {1}}。
IDispatch
如果没有Dim A As IA
Set A = Obj ' QueryInterface
A.MethodA
' Compilation error
' A.MethodB
' If A.Property Then A.MethodC
Dim B As IB
Set B = Obj ' QueryInterface
B.MethodA
B.MethodB
' Compilation error
' If B.Property Then B.MethodC
,Visual Basic会编译缺少的方法调用和属性访问,如果取消注释,则调用[nonextensible]
后跟IDispatch::GetIDsOfNames
。
通常,如果您喜欢编译时检查,这是一件好事,如果需要动态查找,则强制代码将变量声明为IDispatch::Invoke
或Object
。这可能是expando对象的麻烦,但是那些违反了IDispatch
's contract的一点:
IDispatch :: GetIDsOfNames方法
...
的备注强>
...
成员和参数DISPID必须在对象的生命周期内保持不变。这允许客户端获取DISPID一次,并将其缓存以供以后使用。
...
警告您无法使用此方法来访问已动态添加的值,例如通过JavaScript添加的值。而是使用IDispatchEx接口的GetDispID。有关更多信息,请参阅IDispatchEx interface。
...
编辑:以下是您可以尝试使用Word VBA( Alt + F11 )的示例,添加宏并粘贴此文本:
Variant
要试用它,请选择菜单Debug→Compile Project。
它应该成功编译。虽然(默认)接口(for)Dim Docs As Documents
Set Docs = Application.Documents
Docs.Add
' Compilation error
' Docs.Foo
Dim Doc As Document
Set Doc = Docs(0)
Doc.Activate
Doc.Foo
没有Document
方法,但它不是Foo
(小心双重否定),因此调用转为运行时调度。
现在,取消注释[nonextensible]
并重新编译项目。
它应该抛出一个错误,因为(默认)接口(for)Docs.Foo
是Documents
,并且对缺少的[nonextensible]
方法的调用不会转变为运行时调度。