如何避免向接口类进行向下转型?

4
我正在使用Excel VBA(Excel 2010),在尝试使用继承时遇到了问题。基本上,我有一个接口MyInterface和一个实现类MyImplementation。在VBA代码中,当我引用类型为MyInterfaceDim时,我只能访问该接口上定义的成员 - 这是预期的。当我引用类型为MyImplementationDim时,我无法访问它实现的接口上定义的成员 - 这是不可预期的

为什么我不能直接在实现类上调用接口属性

MyInterface

Option Explicit

Public Property Get Text() As String
End Property

我的实现

Option Explicit
Implements MyInterface

'The implementation of the interface method'
Private Property Get MyInterface_Text() As String
  MyInterface_Text = "Some Text"
End Property

Public Property Get MoreText() As String
  MoreText = "Yes, some more text!"
End Property

MainModule - 使用示例

Function Stuff()
  Dim impl As New MyImplementation
  Dim myInt As MyInterface: Set myInt = impl
  'The following line is fine - displays "Yes, some more text!"
  MsgBox impl.MoreText
  'This is also fine - displays "Some text"
  MsgBox DownCast(impl).Text
  'This is also fine - displays "Some text"
  MsgBox myInt.Text
  'This is *not* fine - why??
  MsgBox impl.Text
End Function

Function DownCast(ByRef interface As MyInterface) As MyInterface
  Set DownCast = interface
End Function

主要问题是如何避免强制类型转换?
注意 - 上面的例子是故意编造的。我意识到直接引用实现类通常是不好的做法。
2个回答

6
当我引用类型为MyImplementation的Dim时,我无法访问其实现接口定义的成员 - 这是意外的。解决方法是改变期望值。这是VBA的工作方式:VBA类实现COM接口(如IUnknown),但不公开它们。如果您想从类中公开接口的成员,您必须明确地这样做:
Option Explicit
Implements MyInterface

'The implementation of the interface method'
Private Property Get MyInterface_Text() As String
    MyInterface_Text = "Some Text"
End Property

Public Property Get MoreText() As String
    MoreText = "Yes, some more text!"
End Property

Public Property Get Text() As String
    Text = MyInterface_Text 
End Property

解决方案是改变你的期望。- 呵呵,同意!关于你的答案,我在网上看到过这个解决方案。对于 MyImplementation 的客户端代码,这个解决方案很好,但对于所有实现 MyInterface 的类来说,它并不适用。如果我的接口有10个属性和10个实现类,那么我就必须编写100个方法!从长远来看,这似乎难以维护。无论如何,你说得对:我需要改变我的期望!感谢你的回答 - 已接受! - Muel
快速问题:您是否知道VB.NET是否需要相同的技术?还是它按照我的最初期望工作? - Muel
不,VB.NET 没有这个限制。 - Joe

0

只需将实现方法声明为Public而不是Private即可:

Option Explicit
' Class MyImpl
Implements MyInterface

'The implementation of the interface method'
'Notice the Public here instead of private'
Public Property Get MyInterface_Text() As String
    MyInterface_Text = "Some Text"
End Property

唯一需要记住的是,在调用实现中的方法时,您需要使用更长的名称:
Dim instance as MyImpl
 ' initialize your instance
instance.MyInterface_Text 
' instead of instance.Text

就是这样。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接