# Why use subtypes instead of traits and duck typing?

**URL:** <https://discourse.julialang.org/t/why-use-subtypes-instead-of-traits-and-duck-typing/59146>\
**Category:** General Usage\
**Tags:** inheritance, traits\
**Created:** [April 13, 2021, 4:51am UTC](https://discourse.julialang.org/t/why-use-subtypes-instead-of-traits-and-duck-typing/59146 "2021-04-13T04:51:33Z")\
**Posts on this page:** 1\
**Showing post:** 7

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [April 13, 2021, 1:36pm UTC](https://discourse.julialang.org/t/why-use-subtypes-instead-of-traits-and-duck-typing/59146/7 "2021-04-13T13:36:02Z")

</div>

> [@jakobnissen](#):
>
> My advice would be that, if you are creating a package that exports generally useful types, you should define an abstract supertype, specify its interface in the documentation, and then implement as much of the functionality of your concrete types using methods that take the abstract type. This allows users to subtype your abstract type, implement the interface for their new type, and use most of the code in your package.

I kinda disagree with this. This may lead to the following scenario:

1. A second package is created to make useful operations over types of the abstract supertype exported by the first package (i.e., the package you describe).
2. Some user imports this second package and wants to use it on their own type but their type already subtype an abstract type needed by other interface, or it wants to create a glue package that implements second package interface for a concrete type of a third-party package.
3. If the abstract type did not exist, it would only be a question of defining some primitive operations over the type, and letting the second package do its magic.
4. However, as the second package expects subtypes of some abstract class, and you cannot add those to an already existing type (or to a type that already needs to have another parent type) you need to create a type wrapper, and the process may become much more annoying.

I agree with the feeling shared by @regier2302, it is something that was already in my mind for some time. I even write these [first](https://discourse.julialang.org/t/struct-as-subtype-of-multiple-types/52357/2) and [second](https://discourse.julialang.org/t/struct-as-subtype-of-multiple-types/52357/8) answers to an user with similar but much more applied doubts. I recognize that the type hierarchy is very nice for dispatch on some “set-on-stone” relations like Number (`Real`, `Float64`, `Integer`, `Int`, and so on) it creates a great family of fallbacks for operations over generic numbers.

However, in general, my to-go design is to create modules that just describe an interface, without creating any abstract type and without, therefore, dispatching on abstract types. The interface can be separated in _primitive_ functions, for which there is no fallback; _fallback_ functions for which there is a fallback calling primitive functions, but you can also implement your own behavior; and _purpose_ functions that call both previous types and you often do not want to re-implement because otherwise you have no need for the package, the package’s purpose is to provide them (sometimes those will be in a different package, and a `Base` package will have both _primitive_ and _fallback_ functions). Then anybody can implement as many interfaces they want for their own types, and glue packages can provide the interface of Package `X` to types of Package `Y`. Those interface packages can provide some abstract types (or even concrete, in fact), but only to be used trait-style (functions dispatch on them, but they are just a way passing a flag on type-space). The only thing a tree of abstract types adds to this idea is a hierarchy of fallbacks, that sometimes is nice, but at the cost of incompatibilities between interfaces, because a type cannot subtype multiple types and therefore cannot implement multiple interfaces.

---

_[View the full topic](https://discourse.julialang.org/t/why-use-subtypes-instead-of-traits-and-duck-typing/59146)._
