The Crystal Programming Language Forum

Create hash of something that would return a Class object

I want to create a hash in which I register classes that implement operators in a programming language. Each operator has its own class definition. The class has methods that return type and argument-type information, and I want to know this information before instantiating an object of that class. So, I would like to get the Class object from my registration system.

I can’t create Hash(String, Class) because Class can’t be used as a generic type parameter yet.
I can’t create Proc(Nil, Class) for the same reason.

I have macros that will register all non-abstract derivatives of a class automatically, if only I can arrive at the type of the registration hash.

1 Like

Usually the way you handle this is you type it to some module/parent type (or refactor things so you don’t need to do this). Something like https://play.crystal-lang.org/#/r/9kme.

What would an example value of the key be in this context? Sounds like you’re making some DI system? If so you could checkout https://athena-framework.github.io/dependency-injection/Athena/DependencyInjection.html.

1 Like

[Edit: almost the same as said by @Blacksmoke16]


If you have a common type of the classes you want to register you can use Hash(String, Common.class). This is similar to how crystal-db register a Driver class per uri scheme.

Another similar approach is using modules and make class extend from them. That creates a union of the classes.

The following compiles

module Common
  abstract def description
  abstract def make(v)
end

struct Int32
  extend Common

  def self.description
    "I create Int32"
  end

  def self.make(v)
    raise "not int32"
  end

  def self.make(v : Int32)
    v
  end
end

class String
  extend Common

  def self.description
    "I create String"
  end

  def self.make(v)
    raise "not string"
  end

  def self.make(v : String)
    v
  end
end

h = {} of String => Common
h["int"] = Int32.as(Common)
h["string"] = String.as(Common)

a = h["int"].make(4)
pp!({a, typeof(a), a.class})

b = h["string"].make("str")
pp!({b, typeof(b), b.class})

h["int"].make("str") rescue puts "ERROR: int from str"
h["string"].make(4) rescue puts "ERROR: str from int"

pp! h["int"].description
pp! h["string"].description
1 Like

Thank you both, both of the methods you have suggested work.

1 Like