excel - 我可以转换为任何对象的默认接口(interface)吗?

标签 excel vba interface reference

据我了解,在VBA中,类都公开了一个默认接口(interface)(它只是类模块的名称)。你也可以让它们实现另一个自定义接口(interface);为类提供一些属性,这些属性从自定义界面的角度来看是可见的,但从默认界面的角度来看是不可见的。

我有一个方法需要实现某个接口(interface)的类

Public Sub doStuff(ByVal item As ICustomInterface)

像这样叫

Dim a As New Class1 'Implements ICustomInterface
Dim b As New Class2 'Implements ICustomInterface too

doStuff a
doStuff b
doStuff New Collection 'raises "runtime error 13 - type mismatch" as Collection doesn't implement ICustomInterface

如果我理解正确,当我向该方法提供对象实例时,通过传递对该对象默认接口(interface)的引用,VBA 查询该对象实例以生成对 ICustomInterface 的引用该对象,并将新引用存储在 item 变量中。我认为这个过程称为向下转型。

我的问题是 doStuff 调用的方法需要传递项目的默认接口(interface),不是自定义接口(interface)。


为了演示,我们可以使用ObjPtr 来识别指向哪个接口(interface):

Dim implementation As Object
Dim defaultCast As Class1 'implements ICustomInterface
Dim downCast As ICustomInterface

Set implementation = New Class1 'or Class2 - store reference to default interface in variable

'1) Check if implementation indeed points to default interface
Set defaultCast = implementation
Debug.Assert ObjPtr(defaultCast) = ObjPtr(implementation) 'fine

'2) Check if down-casting gives different interface
Set downCast = implementation
Debug.Assert ObjPtr(downCast) <> ObjPtr(implementation) 'fine

'4) Check if casting from ICustomInterface to Object reverts to default interface
Dim objectUpCast As Object
Set objectUpCast = downCast
Debug.Assert ObjPtr(objectUpCast) = ObjPtr(implementation) 'fails :(
Debug.Assert ObjPtr(objectUpCast) = ObjPtr(downCast) 'succeeds - not what I want

'3) Check if casting from ICustomInterface to Class1 reverts to Class1's default interface
Dim strictUpCast As Class1
Set strictUpCast = downCast
Debug.Assert ObjPtr(strictUpCast) = ObjPtr(implementation) 'fine - but won't work if I Set implementation = New Class2
'/some other implementation of the ICustomInterface

第三种选择;采用自定义界面并恢复到默认界面是我想要的

为什么?

我想在我的函数签名中使用类型安全。我可以明确地使用自定义界面 - 这是我当前的解决方法

Public Sub doStuff(ByVal item As Object) 'receive default interface - or at least whatever interface is provided

    Dim downCast As ICustomInterface
    Set downCast = item

    'work with downCast as necessary
    '... later pass default interface "item" to other sub

End Sub

但我更喜欢检查函数签名中的类型然后在需要时向上转换回默认接口(interface)的工作流程

最佳答案

首先转换为 IUnknown:

    Dim objectUpCast As Object
    Dim iUnk As IUnknown
    Set iUnk = downCast
    Set objectUpCast = iUnk

编辑

所有 VB 接口(interface)都是双重接口(interface),这意味着所有接口(interface)都派生自 IDispatch,后者又派生自 IUnknown。

请注意,Object 数据类型代表 IDispatch 接口(interface)。

在你的例子中:

Dim strictUpCast As Class1
Set strictUpCast = downCast

第二行调用 QueryInterface 请求 Class1 接口(interface),正如预期的那样。

在你的另一个例子中:

Dim objectUpCast As Object
Set objectUpCast = downCast

在第二行可能会发生两件事:

  1. 如果变量 (downCast) 指向双重接口(interface)(从 IDispatch 派生的接口(interface)),那么 VB 只会增加引用计数(因此返回与 downCast 相同的接口(interface))
  2. 如果变量指向自定义接口(interface)(派生自 IUnknown),则 VB 调用 QueryInterface 并请求 IDispatch 接口(interface)

当转换到 IUnknown 接口(interface)(OLE 自动化库的一部分)时:

Dim iUnk As IUnknown
Set iUnk = downCast

iUnk 变量指向自定义接口(interface)(仅派生自 IUnknown)。

这得到:

Dim objectUpCast As Object
Set objectUpCast = iUnk

其中,在第二行,VB 调用 QueryInterface 并请求 IDispatch 接口(interface),因为变量(右侧)指向自定义接口(interface)(IUnknown 本身不是从 IDispatch 派生的)。 IDispatch 接口(interface)知道默认接口(interface),这就是返回的内容

关于excel - 我可以转换为任何对象的默认接口(interface)吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57536331/

相关文章:

excel - 如何使用 VBA 根据条件删除 Excel ListObject 中的行?

excel - 添加到字典时 VBA 错误 457 键

json - 如何使用 Excel vba 从 json 字符串中的 json 对列表中找到最大值?

excel - 在excel中显示一周的日期范围

vba - 优化 VBA 文本搜索

excel - 如何在工作表上设置保护但启用大纲和过滤器,重新启动后可用?

vba - 寻找在 VBA 中使用的函数式最小化器

java - 从实现接口(interface)的类调用方法 (java)

go - 如何在golang中结合接口(interface)和结构?

java - 确定类的扩展接口(interface)