Motivation behind the question
I've been learning how to do Object Composition in Javascript using Concatenative Inheritance and wondered how I could accomplish something similar in VBA (which doesn't have inheritance).
Object Composition: I'm trying to figure out how to accomplish a "has a" relationship vs. a "is a" relationship. I want to be able to write simple behavior classes where they can be used by combining them together to make more complex classes.
I've created a simple example to demonstrate what I'd like to accomplish.
Example use case
Testing Module
Here are some examples of what might be used. For this question though, I'll just focus on the example use of the Fighter
class.
The Fight
method is actually calling the Fight
method in the CanFight
class. It debugs a message and reduces stamina by 1.
'MOST EXCITING GAME OF ALL TIME! =)
Private Sub StartGame()
Dim Slasher As Fighter
Set Slasher = New Fighter
Slasher.Name = "Slasher"
Slasher.Fight '-> Slasher slashes at the foe!
Debug.Print Slasher.Stamina '-> 99
'MAGES CAN ONLY CAST (ONLY HAS MANA)
Dim Scorcher As Mage
Set Scorcher = New Mage
Scorcher.Name = "Scorcher"
Scorcher.Cast "fireball" '->Scorcher casts fireball!
Debug.Print Scorcher.Mana '-> 99
'CAN BOTH FIGHT & CAST (HAS BOTH STAMINA & MANA)
Dim Roland As Paladin
Set Roland = New Paladin
Roland.Name = "Roland"
Roland.Fight '-> Roland slashes at the foe!
Roland.Cast "Holy Light" '-> Roland casts Holy Light!
End Sub
Fighter Class
This class has two public properties Name
and Stamina
.
This class also contains FightAbility
which is an instance of the CanFight
class. This is my attempt at trying to accomplish composition.
Option Explicit
Private FightAbility As CanFight
Private pName As String
Private pStamina As Long
Private Sub Class_Initialize()
pStamina = 100
Set FightAbility = New CanFight
End Sub
Public Property Get Name() As String
Name = pName
End Property
Public Property Let Name(ByVal Value As String)
pName = Value
End Property
Public Property Get Stamina() As String
Stamina = pStamina
End Property
Public Property Let Stamina(ByVal Value As String)
pStamina = Value
End Property
'This is the function that uses the ability to fight.
'It passes a reference to itself to the `CanFight` class
'giving it access to its public properties.
'This is my attempt at composition.
Public Sub Fight()
FightAbility.Fight Me
End Sub
CanFight Class
This is the class that can be reused for other characters. An Example is a Paladin
class might need to also have the ability to fight.
The obvious issue with how this is laid out is that state
is an Object
. The user won't know it needs to have Stamina
and a Name
property unless they look at the code.
Option Explicit
Public Sub Fight(ByRef State As Object)
Debug.Print State.Name & " slashes at the foe!"
State.Stamina = State.Stamina - 1
End Sub
Summarizing the question
My example feels broken since there is no structure in place as far as what properties are needed in order to use it.
At the same time, I want to make sure my game characters can be flexible in having their own distinct properties. Examples from above:
Fighter
uses:canFight
(stamina)Mage
uses:canCast
(mana)Paladin
uses both:canFight
(stamina) andcanCast
(Mana)
If I created an ICharacter
interface class then I feel like it would be locked into having all the properties for all types of Characters.
My question is how do I achieve structured but flexible Composition like this in VBA?