Suppose you’re building a medieval role playing game, you’re going to have weapons of different types, so you’ll create an abstract type called Weapon:
abstract type GameObject end
abstract type Weapon <: GameObject end
You decide that your charcters can cast spells, and spells also have different types, so you can do:
abstract type Spell <: Weapon end # Fireball, Freeze, etc...
The problem? Not every spell is considered a Weapon. Suppose you want a spell that manipulates nature, for example, a spell that makes a planet grow faster or a spell that makes spoiled food suddenly fresh again.
I could make Spell a direct sub type of GameObject, and then Nature and Defense
abstract type Spell <: GameObject end
abstract type Nature <: Spell # FreshFood, GrowPlant,etc...
abstract type Defense <: Spell # Fireball,Freeze, etc...
When you have a sub types that share attributes of different abstract types, how do you model it?
You can do a kind of multiple inheritance with subtyped traits. Edit: But this is probably overcomplicating things normal traits are all you need here.
You could also use regular object composition and multiple dispatch.
My first response is to generally caution you about overusing complex type hierarchies. In
general, types should be used strictly for dispatch; until you have a function that you need
to dispatch differently for one set of types versus another, abstract parent types shouldn’t
be introduced.
But if you do need to control dispatch in a way where simple single-inheritance won’t work,
you can use a “Holy trait”:
struct HasMyTrait end
struct HasntMyTrait end
mytrait(_) = HasntMyTrait()
struct MyType end
mytrait(::MyType) = HasMyTrait()
myfunc(x) = _myfunc(x, mytrait(x))
_myfunc(x, ::HasntMyTrait) = ... # Behavior for types without trait
_myfunc(x, ::HasMyTrait) = ... # Behavior for types with trait
There are several packages that try to wrap this pattern into a macro to make it more
pleasant to use, but I’m not personally familiar enough with any of them to make a
recommendation.