I’m translating some Python code to Julia and am trying to figure out how to map the usage of class methods to Julia. See below for a Python-style outline of what I’m porting. There’s a single abstract class with one or more concrete subclasses. Each concrete subclass implements an action that is applied to a state (it’s code from a game simulation). One particular thing is that each subclass can generate actions of its type from the current game state, which is what generate()
does. It returns a list of one or more actions that can later be applied to a state by calling execute()
on the instance, passing the state to apply to.
ACTION_CONCRETE_A = 1
ACTION_CONCRETE_B = 2
...
class AbstractAction:
def __init__(self, type, ...):
# Hold some general fields
self.type = type
....
class ConcreteActionA(AbstractAction):
@classmethod
def generate(cls, state, ...):
# Returns a list of one or more instances
# of ConcreteAction possible in this state
return [ConcreteActionA(...), ...]
def __init__(self, ...):
AbstractAction.__init__(self, ACTION_CONCRETE_A, ...)
# Action specific fields
...
def execute(self, state):
# Apply the action to a state
...
state = <game state>
actions = ConcreteActionA.generate(state)
# Pick a random action and execute it
action = random.choice(actions)
action.execute(state)
Porting the class structure doesn’t seem to be too hard (apart from the composition versus forwarding choice), including the constructor and execute()
method, something like this:
@enum ActionType
ACTION_CONCRETE_A
....
end
abstract type AbstractAction end
mutable struct ConcreteActionA <: AbstractAction
type::ActionType
# ...more action-specific fields
function ConcreteActionA(...)
obj = new(ACTION_CONCRETE_A)
# Initialize other fields....
return obj
end
end
function execute(action::ConcreteActionA, state::State)
# ....
end
But what’s a good way to port generate()
? Ideally I would be able to call
actions = generate(ConcreteActionA, state)
but I’m having trouble figuring out how to dispatch on a struct type (in contrast to a struct value), as I have many different forms of generate()
, one for each action type. I looked into symbols to see if those could be usable here (e.g. :ConcreteAction
), but I’m not clear whether that is a good method.
Any hints?