# Style recommendation for enum as type

**URL:** https://discourse.julialang.org/t/style-recommendation-for-enum-as-type/46078
**Category:** General Usage
**Tags:** enum
**Created:** [September 4, 2020, 9:42pm UTC](https://discourse.julialang.org/t/style-recommendation-for-enum-as-type/46078 "2020-09-04T21:42:42Z")
**Posts on this page:** 1
**Showing post:** 4

<div class="post-metadata">

### Author: ![MatthijsCox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/matthijscox/32/42831_2.png) [@MatthijsCox](https://discourse.julialang.org/u/MatthijsCox)
#### Post date: [December 23, 2020, 1:11pm UTC](https://discourse.julialang.org/t/style-recommendation-for-enum-as-type/46078/4 "2020-12-23T13:11:56Z")

</div>

Hi I totally recognize this question. I often find myself wondering if I should write an @enum or just make an abstract type with “values” as subtypes. When I want to dispatch on the values, then I will now always write the abstract type myself. And almost always do I find a reason to dispatch on the values. And I often create a mapping to an Integer. But it just _feels_ like an enum.

Here’s some example code that I often find myself writing. I would love some advice/discussion on the best pattern for these things. Maybe it’s just fine. I was totally influenced by this [blog about julia dispatching enum versus type](https://www.juliabloggers.com/julia-dispatching-enum-versus-type/).

```julia
using Test

module MyModule

    using InteractiveUtils

    export SomeType, First, Second, Third, Fourth

    abstract type SomeType end
    struct First <: SomeType end
    struct Second <: SomeType end
    struct Third <: SomeType end
    struct Fourth <: SomeType end

    Base.Integer(T::Type{<:SomeType}) = Integer(T())
    Base.Integer(::First) = 1
    Base.Integer(::Second) = 2
    Base.Integer(::Third) = 3
    Base.Integer(::Fourth) = 4

    const SomeTypeSet = subtypes(SomeType)

    function Base.convert(::Type{SomeType}, x::Integer)
        for e in SomeTypeSet
            x==Integer(e) && return e()
        end
    end
    SomeType(x::Integer) = convert(SomeType, x)

    Base.isless(x1::SomeType, x2::SomeType) = isless(Integer(x1), Integer(x2))
    Base.isless(x1::Type{<:SomeType}, x2::Type{<:SomeType}) = isless(x1(), x2())

end

@testset "this feels like an enum" begin
    using .MyModule

    # You want to use either the type or the instance of the type as values
    # but you can also use both this way:
    @test First() < Fourth()
    @test First < Fourth
    @test SomeType(3) == Third()
end

```

If you use these things as a property of a type, then it’s a trait right?  
`get_trait(::Type{MyFirstType}) = First()`

If you use these things as a property of an instance of a type, then it _feels_ like an enum. Like the color of a banana:

```julia
abstract type Color end
struct Yellow <: Color end
struct Brown <: Color end

mutable struct Banana
    color::Color
    weight::AbstractFloat
end

eat(b::Banana) = eat(b.color, b)
eat(::Yellow, ::Banana) = println("yummy")
eat(::Brown, ::Banana) = println("eeww")

```

---

_[View the full topic](https://discourse.julialang.org/t/style-recommendation-for-enum-as-type/46078)._
