Suppose I am trying to describe the behavior of a Pet
. I implemented several methods common to all instances of Pet
e.g. eat(pet::Pet)
and walk(pet::Pet, towards)
. I also want to define
function greet(pet::Pet, person::Person)
walk(pet,person)
say_hello(pet)
# do some other stuff
end
where say_hello()
depends on whether Pet
is a Cat
or a Dog
e.g.
say_hello(::Dog) = bark()
say_hello(::Cat) = meow()
The key idea is that greet
performs some action common to all Pet
instances but also some action that depends on which subtype of Pet
it is. In the MWE above, greet
is pretty simple and sequential but in principle it could be more complicated, and say_hello
could be called in some loop, or be called multiple times, etc. Moreover, I’d like other people to be able to define other kinds of Pet
’s who say_hello()
in other ways without my code for greet()
needing to be aware of that.
In an OOP language, I would implement this as something like this (pseudocode):
class Pet {
abstract say_hello();
eat() {
internal_eat();
}
walk(towards) {
internal_walk();
}
function greet(towards) {
walk(person)
say_hello(pet)
# do some other stuff
}
}
class Dog extends Pet {
say_hello() {
bark()
}
}
class Cat extends Pet {
say_hello() {
meow()
}
}
where internal_eat()
, internal_walk()
, bark()
, and meow()
are “private” methods of their respectiveclasses.
Now, I can’t do this in Julia, so the best alternative I can think of is:
struct Pet{F<:Function}
say_hello::F
end
eat(pet::Pet) = internal_eat(pet)
walk(pet::Pet, person::Person) = internal_walk(pet, person)
function greet(pet::Pet, person::Person)
walk(pet, person)
pet.say_hello()
end
dog = Pet(bark())
cat = Pet(meow())
But this looks kind of ugly, is hard to read, doesn’t feel very Julian, and just seems like I’m trying to recreate OOP instead of buying into a different/better paradigm.
How do I think about this problem in a more Julian way?
BTW, if the MWE is too contrived, the problem that inspired it is a class of models that are all solved in the same way, but where the specifics of one step of the solution depend on the specifics of the model – not just parameters but equations, too.