I’m not an expert on the other packages, but I’ll try to summarize the differences as I see them. First I’ll start with more details about the approach and philosophy of MultipleInterfaces.jl.
MultipleInterfaces.jl
MultipleInterfaces.jl has two main goals:
- Provide a simple and ergonomic way to define a DAG of related interfaces, via multiple inheritance of interfaces.
- Allow multiple dispatch on those interfaces.
And a secondary goal:
- Provide interface intersections that can be dispatched on, like
Foo & Bar
.
MultipleInterfaces.jl claims to be about interfaces, but in reality it’s an alternative type system with abstract multiple inheritance.
Although MultipleInterfaces.jl provides an alternative type system, the spirit of the type system (“interfaces”) in MultipleInterfaces.jl is very similar to the spirit of the Julia type system:
- It’s a nominal type system.
- All interfaces are abstract. Concrete types are final.
- In analogy to abstract types in Julia, interfaces do not enforce anything about their implementors. They are only used for dispatch.
One of the original inspirations for MultipleInterfaces.jl was the About Interfaces section of @Sukera’s RequiredInterfaces.jl documentation, which, if I recall correctly, discusses multiple inheritance and proposes that interfaces should not contain optional methods. Multiple inheritance provides more flexibility in composing different interfaces, so if we have multiple inheritance we shouldn’t really need “optional” interface methods anymore.
I was also inspired by Haskell type classes, Rust traits, and Java interfaces, all of which support abstract multiple inheritance. I want to be able to define a DAG of interfaces similar to this DAG of type classes in Haskell:

(Image from the Haskell wikipedia page.)
As mentioned, MultipleInterfaces.jl does not enforce any requirements on types that declare that they implement an interface. I recommend that developers who define interfaces also create a unit test suite to test objects that implement that interface, possibly with the help of Supposition.jl.
RequiredInterfaces.jl
RequiredInterfaces.jl seems to be focused mainly on ensuring that an interface implementation has implemented all the methods that are required by the interface. It uses regular abstract types as the flags for an implicit interface, which means that there is no mechanism for abstract multiple inheritance.
Interfaces.jl
Interfaces.jl seems to be focused on testing that an interface has been properly implemented. It allows interfaces to have optional methods. That makes sense in the context of the current Julia ecosystem, but I think optional methods cause a lot of headaches.
Dispatching on interfaces is not really provided by Interfaces.jl. I think Interfaces.jl provides some kind of trait object that can be used in a Holy-trait style, but it’s not well documented. And there is currently no support for multiple inheritance of interfaces. (Actually, I don’t see support for single inheritance of interfaces, either.)
DuckDispatch.jl
DuckDispatch.jl might be the closest to MultipleInterfaces.jl. However, there are some differences:
- It uses a structural type system (inspired by Go) rather than a nominal type system.
- Based on the README, it looks like DuckDispatch.jl might impose more requirements on the required methods, whereas MultipleInterfaces.jl takes the traditional Julia approach of relying on docstrings and unit tests to define the expected behavior of the interface.
- I can’t tell if DuckDispatch.jl supports multiple inheritance of
DuckType
s.
Perhaps @mrufsvold can comment more on the details of DuckDispatch.jl and how it differs from MultipleInterfaces.jl.