# Which is better for traits? Subtyping vs parametric typing

**URL:** <https://discourse.julialang.org/t/which-is-better-for-traits-subtyping-vs-parametric-typing/115899>\
**Category:** General Usage\
**Tags:** question, traits\
**Created:** [June 20, 2024, 2:47am UTC](https://discourse.julialang.org/t/which-is-better-for-traits-subtyping-vs-parametric-typing/115899 "2024-06-20T02:47:51Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![paalon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paalon/32/5784_2.png) [@paalon](https://discourse.julialang.org/u/paalon)\
**Post date:** [June 20, 2024, 2:47am UTC](https://discourse.julialang.org/t/which-is-better-for-traits-subtyping-vs-parametric-typing/115899/1 "2024-06-20T02:47:51Z")

</div>

I want to define traits (I don’t know so much about traits but perhaps traits). I know 2 ways.

Abstract type and subtypes:

```julia
abstract type YAMLVersion end

struct YAMLV1_1 <: YAMLVersion end

struct YAMLV1_2 <: YAMLVersion end

forwardchars!(::YAMLV1_1, stream::TokenStream, n::Integer=1) #...

```

The way of Julia Base’s [`RoundingMode`](https://github.com/JuliaLang/julia/blob/a14cc38512b6daab6b8417ebb8a64fc794ff89cc/base/rounding.jl#L48)

```julia
struct YAMLVersion{T} end

const YAMLV1_1 = YAMLVersion{:Version1_1}()

const YAMLV1_2 = YAMLVersion{:Version1_2}()

forwardchars!(::YAMLVersion{:Version1_1}, stream::TokenStream, n::Integer=1) #...

```

which is better?

---

<div class="post-metadata">

**Author:** ![Satvik](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/satvik/32/20486_2.png) [@Satvik](https://discourse.julialang.org/u/Satvik)\
**Post date:** [June 20, 2024, 3:38am UTC](https://discourse.julialang.org/t/which-is-better-for-traits-subtyping-vs-parametric-typing/115899/2 "2024-06-20T03:38:01Z")

</div>

The first version is definitely more common, and what I would use most of the time. I’m really not sure why `RoundingMode` uses the struct method, I would guess it’s to solve a specific and niche problem.

---

<div class="post-metadata">

**Author:** ![barucden](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barucden/32/26154_2.png) [@barucden](https://discourse.julialang.org/u/barucden)\
**Post date:** [June 20, 2024, 7:41am UTC](https://discourse.julialang.org/t/which-is-better-for-traits-subtyping-vs-parametric-typing/115899/3 "2024-06-20T07:41:59Z")

</div>

I’d be curious why `RoundingMode` is implemented the way it is! I don’t see the reason.

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [June 20, 2024, 10:52am UTC](https://discourse.julialang.org/t/which-is-better-for-traits-subtyping-vs-parametric-typing/115899/4 "2024-06-20T10:52:36Z")

</div>

> [@paalon](#):
>
> `YAMLVersion{:Version1_1}`

A downside of this approach is decreased type safety, because constructing `YAMLVersion` subtypes with arbitrary parameters is possible.

> [@paalon](#):
>
> I know 2 ways.

Here’s a third way:

```julia
struct YAMLV1_1 end
struct YAMLV1_2 end
const YAMLVersion = Union{YAMLV1_1,YAMLV1_2}

```

Its distinguishing feature is that it doesn’t allow adding more subtypes of `YAMLVersion`.
