I'm just writting an Exception, which should stores a Class
object as a field for the error message process.
class BadType < Exception
getter should_be : Class
getter actual : Class
end
def feed(pet : Animal, food : Food)
raise BadType.new should_be: Cat, actual: pet.class if food == "fish" && !pet.is_a?(Cat)
end
But, Class
is abstract so cannot be used here as a field type.
So, how to solve this in my case? I hadn't found any derived class of Class
, so does it mean one can never store a Class
object as a field? But here my problem is a meaningful usage for this (any type check depends on input may require this BadType
).
I'm not sure whether I missed something, so I came here first.
Class
can't (yet) be used as a ivar type. Maybe it never will, I don't know.
But you can actually use generics for concrete data types, inferred from the arguments to the constructor:
# possible workaround
class Foo(T, U)
def initialize(@bar : T, @baz : U)
end
end
Foo.new String, Int32
I don't know your exact use case, but chances are you don't really need these values as classes. You probably can't do much with it anyway and drawing from your example I guess it's mostly for showing debugging information.
So it is very likely that just storing the names of the classes (as strings) would be a better solution for this problem.
# better solution
class Foo
@bar : String
@baz : String
def initialize(bar : Class, baz : Class)
@bar = bar.name
@baz = baz.name
end
end
Foo.new String, Int3
The generic arguments mean a new concrete type is created for every combination of classes used with Foo
. That can have an impact on compiler performance.
I would most definitely use strings for this. Even if you need the classes for some particularly processing later on, it's probably better to just map the strings to the constants using a macro-generated lookup table.