CPhil
CPhil

Reputation: 927

Define an empty Dict where the values are the subtype of an abstract type

I've got an abstract type, with subtypes. I'd like to make and add to a Dict that holds the subtypes. Is this doable? What's a better way of achieving this?

Example:

abstract type Cat end

struct Lion <: Cat
   manecolour
end

struct Tiger <: Cat
   stripewidth
end

cats = Dict{Int, <:Cat}()

gives

ERROR: MethodError: no method matching Dict{Int64,var"#s3"} where var"#s3"<:Cat()

What's the more correct way of doing this?

Upvotes: 4

Views: 380

Answers (3)

Przemyslaw Szufel
Przemyslaw Szufel

Reputation: 42214

If the number of Cat types is small you can avoid using abstract container to boost the performance:

cats = Dict{Int, Cat}()
cats[1] = Lion(12)

cats2 = Dict{Int, Union{subtypes(Cat)...}}()
cats2[1] = Lion(12)

Now testing (I am using Tiger and Lion cat types):

julia> @btime $cats[1].manecolour == 12;
  25.300 ns (0 allocations: 0 bytes)

julia> @btime $cats2[1].manecolour == 12;
  17.434 ns (0 allocations: 0 bytes)

Upvotes: 1

Jakob Nissen
Jakob Nissen

Reputation: 1991

Types are of the type DataType - except UnionAlls. So you could do

julia> d = Dict{Int, Union{DataType, UnionAll}}()
 Dict{Int64,Union{DataType, UnionAll}}()

julia> for (i, type) in enumerate(subtypes(Integer))
           d[i] = type
       end

julia> d
 Dict{Int64,Union{DataType, UnionAll}} with 3 entries:
  2 => Signed
  3 => Unsigned
  1 => Bool

Upvotes: 1

fredrikekre
fredrikekre

Reputation: 10984

Just use the abstract type as the container type: cats = Dict{Int, Cat}():

julia> cats = Dict{Int, Cat}()
Dict{Int64,Cat}()

julia> cats[1] = Lion(12)
Lion(12)

julia> cats
Dict{Int64,Cat} with 1 entry:
  1 => Lion(12)

Upvotes: 5

Related Questions