fre*_*oft 4 collections polymorphism excel inheritance vba
关于Excel VBA的一个简单问题:如果"Sheets"对象是一个集合,为什么下面的句子返回false?(在中级面板中输入)
debug.print TypeOf Sheets Is Collection
Falso
Run Code Online (Sandbox Code Playgroud)
我发现它是因为我创建了一个以Collection作为参数的函数.该函数适用于我声明为Collection的变量,但不适用于其他集合(例如Sheets集合).
也许VBA失败的继承和/或多态?
编辑:正如JosieP和mehow所解释的那样,Sheets集合不会继承Collection类/接口,因此它不是Collection,也不能以多态方式用作Collection.
所以现在的问题是:为什么Sheets不是Collection的子类?为什么他们没有继承Collection?鉴于已经在Sheets中实现的方法/属性,它应该是小菜一碟.我可以看到,Collection类/接口只需要4个方法:
Add
Count
Item
Remove
Run Code Online (Sandbox Code Playgroud)
而Sheets已经实现了4个类似的方法/属性:
Add
Count
Item
Delete
Run Code Online (Sandbox Code Playgroud)
因此映射将是微不足道的.他们可以轻松地将Sheets集合转换为Collection.
编辑2:我感谢mehow关于询问MS的建议,但我不会这样做,因为他们可能会说"这不是设计错误,它是一个功能":).更多思考的食物:在新工作簿中运行以下代码:
Sheets.Add.name = "sh2"
Sheets.Add.name = "sh3"
Dim col As Collection
Set col = New Collection
col.Add Sheets(1)
col.Add Sheets(2)
col.Add Sheets(3)
For Each ele In col
Debug.Print "ele in col: " & ele.name
Next ele
For Each ele In Sheets
Debug.Print "ele in Sheets: " & ele.name
Next ele
Run Code Online (Sandbox Code Playgroud)
我很奇怪,"col"和"Sheets"都可以以相同的方式迭代,使用"for each"循环,但它们不共享一个公共接口.如果我必须设计类,层次结构将是:
iIterable (interface)
|
|
iCollection (interface)
/ \
/ \
/ \
Collection cSheets (classes)
Run Code Online (Sandbox Code Playgroud)
和Sheets将是cSheets类的对象(实例).
通过这种方式,我创建的函数(当前采用Collection参数)将采用iCollection参数,因此它既可以使用Collection实例,也可以使用Sheets.
小智 6
Sheets
是Object
类型的集合,而不是类型的对象Collection
.
就像JosieP说的那样
Sheets类不从VBA Collection继承,也不实现Collection接口(例如,没有Remove方法)
应该足以理解.
Sub Main()
Dim c As Collection
Set c = New Collection
Debug.Print VarType(c), TypeOf c Is Collection
Debug.Print VarType(Sheets), TypeOf Sheets Is Object
End Sub
Run Code Online (Sandbox Code Playgroud)
为了确认打开Object Browser
与F2和类型找到Sheets
向Microsoft提出第二个问题.但是请记住,Collection
可以是空的,而Sheets
总是需要至少有一个Sheets或Chart对象.
很多东西都依赖于Excel中的Sheets集合对象,这就是为什么我认为它必须是一个单独的类.通过实现ICollection接口并提供单独的实现,我看不出有什么问题,但就像我说的那样问微软(好问题)
该for each
循环是可能的,因为每个VBA类有属性.并非所有属性都可以通过IDE看到,但它们确实存在(更多的VB6常识而不仅仅是对VBA的引用).
好的,现在回答你的第三个问题.您可以遍历集合,因为它实现了IUnknown接口NewEnum()
(可启动方法).您在类型集合上指定默认迭代对象(在表格案例中为其Sheets集合).
有关可枚举方法的更清晰说明,请参阅此链接.
请参阅此答案以更好地了解迭代是如何实现的.
归档时间: |
|
查看次数: |
1235 次 |
最近记录: |