Types with multiple supertypes

Hey everybody,

I have a model in which I can have different setups. There are in principle 2x2 combinations. Let’s say models can be A1, A2, B1, B2.

I now have types that are specialized for each type. Some function behaviour, however, is common to A-models, whereas other function behave the same for 1-models. For some a specialized method for A1, A2, etc. is necessary.

Is it possible to define types with multiple supertypes? For example, A1 <: A, but also A1 <: 1. If that is not possible, what kind of design pattern would you suggest?

Edit — to answer the original question: no, that kind of multiple “inheritance” is not possible.

You could use type parameters:

struct Model{S, T}
    ...
end

A1object = Model{:A, :1}()

B1object = Model{:B, :1}()

A2object = Model{:A, :2}()

B2object = Model{:B, :2}()

and then dispatch the desired behavior based on the two parameters:

f(obj::Model{S, :1}) where S = ... # only applies to the 1s
f(obj::Model{:A, T}) where T = ... # only applies to the As

and so on.

4 Likes

Thank you, I’ll keep that in mind when I refactor my code the next time :slight_smile:

I would use multiple dispatch passing both model types as variables. Example:

abstract type LetterModel end
abstract type NumberModel end

struct A <: LetterModel
struct Num1 <: NumberModel

f(letter::LetterModel, number::NumberModel) # generic implementation
f(letter::A, number::NumberModel) # uses A, but ignores Number
f(letter::B, number::Num2) # Specialized method on both B and 2

3 Likes

Thank you, after some thinking, this is what I will do. In my case, my model is indeed defined by two sets of parameters. One set is related to the letter component, whereas the other one is related to the number component. Then I can define functions just the way you did :slight_smile:

1 Like