Fed*_*nis 3 oop inheritance vba catia
在这个问题上展开一点VBA 继承模式
我在 VBA 中重现了一个基本的继承模式,但我想了解是否有更有效和更简洁的方法来实现这一点。
考虑这个小测试用例。
IAnimal.cls
'declaration
Public Sub eat()
End Sub
Public Sub breathe()
End Sub
Run Code Online (Sandbox Code Playgroud)
Animal.cls :超类
Implements IAnimal
' method implementation
Private Sub IAnimal_eat()
Debug.Print "I'm eating something..."
End Sub
Private Sub IAnimal_breathe()
Debug.Print "I'm brething..."
End Sub
Run Code Online (Sandbox Code Playgroud)
Cat.cls :Animal 的一个子类
Private super As IAnimal
Implements IAnimal
Private Sub Class_Initialize()
Set super = New Animal
End Sub
'#------------------------------------------------
' methods called when object is accessed as an IAnimal implementor.
' I HAVE TO re-implement all of them also here in the subclass (in java I don't need to. It's sufficient to implement them in the superclass)
Private Sub IAnimal_eat()
Me.eat
End Sub
Private Sub IAnimal_breathe()
Me.breathe
End Sub
'#--------------------------------------------------
' subclass-only methods
' To access those methods I MUST DECLARE the object as Cat (Dim tom as Cat)
Public Sub meow()
Debug.Print "meow..."
End Sub
'#------------------------------------------------
' superclass methods
' Since I need to declare the cat object as a Cat (see above)
' I'm FORCED TO explicitly re-implement all of the superclass methods,
' even those that I don't need to override
' otherwise I can't access them
'@Override
Public Sub eat()
Debug.print "I'm eating a fish!"
End Sub
'I'm forced to re-implement also this method, in order to use it directly on a *Cat* object
'@Unnecessary-Override
Public Sub breathe()
super.breathe
End Sub
Run Code Online (Sandbox Code Playgroud)
测试数据库
Sub Main()
Dim snowball As IAnimal
Set snowball = New Cat
Dim tom As Cat
Set tom = New Cat
snowball.meow 'ERROR Method or data member not found <---- cannot access the Cat-only method "meow"
tom.meow '<--- prints "meow"
' creates a Dog, another subclass of Animal
Dim pluto As Dog
Set pluto = New Dog
'create a collection for all my animals
Dim myPets As Collection
Set myPets = New Collection
myPets.Add tom
myPets.Add pluto
Call feed(myPets) '<---- prints
'I 'm eating a fish
'meow...
'I 'm eating a bone
'woof...
End Sub
' a routine for showing how to manage an heterogeneous collection of animals
Sub feed(animals As Collection)
For Each a In animals
a.eat
If TypeOf a Is Cat Then
a.meow
End If
If TypeOf a Is Dog Then
a.woof
End If
Next
End Sub
Run Code Online (Sandbox Code Playgroud)
通过这样做,我可以:
eat()Cat 和 Dog 对象上的方法并具有特定的 Overridden 行为meow())feed的 Animal集合传递给子程序,该子程序可以“安全地”调用 Animal 超类方法并触发基于 Animal 子类的特定代码这似乎有效但很麻烦:假设您需要实现许多 Animal 子类(Dog、Bird、Armadillo、Platypus、Demogorgon 等)。上面的模式迫使你:
所以问题是:有没有更有效/简洁的方法来实现这个例子(并限制每个子类的代码重写)?
tom不应该首先声明As Cat;该feed程序是多余的:
Sub Main()
Dim tom As IAnimal
Set tom = New Cat
tom.eat
End Sub
Run Code Online (Sandbox Code Playgroud)
现在,在Cat类中,这些成员不需要存在:
'Superclass methods --- I have to explicitly override all methods :(
Public Sub eat()
super.eat
Debug.print "...a fish!"
End Sub
Run Code Online (Sandbox Code Playgroud)
在 SOLID/OOP 中,您针对接口而不是具体类型进行编码 - 这就是为什么tom是 anIAnimal而不是Cat. 通过它的IAnimal接口访问,Cat.eat是完全多余的,并暗示 aCat做某事IAnimal不做,这违反了 SOLID 原则:突然间 anIAnimal是 a变得相关,Cat它不应该是,因为多态允许IAnimal是任何东西,和Liskov 替换原则(LSP - “SOLID”的“L”)说任何与 anIAnimal一起工作的代码都应该能够以相同的方式工作,而不管它给出了该接口的什么实现。
遵守这些原则意味着任何IAnimal实现都不应该IAnimal在其默认接口(例如Cat.eat, vs IAnimal.eat)上有成员的副本,这完全消除了您的观点#2:
- 重新实现(再次)所有方法,以从子类公开它们,即使不需要覆盖。
至于第1点...
- 重新实现 IAnimal 接口的所有方法
这是编译器的要求,而不是 VBA 的怪癖:无论是在 Java、C# 还是 VBA 中,您都不能说“我正在实现一个接口”……而不实现其成员。当然 Java 和 C# 允许类继承,所以你的基类可以说“我正在实现一个接口”,实现所有成员,派生类会很高兴地继承它们 - 但是,那是继承,不再是组合。