Why use subtypes instead of traits and duck typing?

Thinking about my last comment… it does seem to mean there essentially no difference between a concrete type inheriting from and abstract type, and traits. Subtyping inheritance for abstract types is just a nice general way of defining a tree structure to specify traits.

Then subtyping inheritance for a concrete type is like an unnamed, default trait, with syntactic sugar.

But you can have multiple subtyping trees of arbitrary specificity for dispatch:

somfunction(object::AbstractType, trait1::Val{<:AbstractTrait1}, trait2::Val{<:AbstractTrait2}) = ...

And the first is not special.