Hello, I need a variable of type Class
and I found the following behaviors:
I can do this:
puts typeof(Bool | Int32 | Int64 | String)
# => (Bool | Int32 | Int64 | String).class
but not this (why?):
c : typeof(Bool | Int32 | Int64 | String) = Bool
# => Error: type must be (Bool | Int32 | Int64 | String).class, not Bool.class
also I can do this:
c : Bool.class | Int32.class | Int64.class | String.class = Bool
puts typeof(c) # => Class (!!!)
puts c # => Bool
Look at this! typeof(c)
is Class (so, union of several Classes is aggregated to the Class and it works)!
but I can’t do this:
c : Class = Bool
puts c
# => Error: can't use Object as the type of a variable yet, use a more specific type
Can’t use Class
as type directly - but look at example above, when union is aggregated to the Class
Is this OK?
I’m really wondering what’s your use case
We have dozens of “Entity” classes and we need to store some internal metadata about relations etc., so we need an attribute (instance variable) with type “Class” to point to our relation class.
It’s not about use case - it’s just an instance variable (or simple variable) that stores Class - simple.
And that work with Classes is a little strange as you can see.
The type of a union of classes is different than the union of classes.
So in:
c : typeof(Bool | Int32 | Int64 | String)
the only thing you can assign is Bool | Int32 | Int64 | String
, while in:
c : Bool.class | Int32.class | Int64.class | String.class
you can assign any of Bool
, Int32
, etc.
I think in the past both types were equal or resolved to a same time and I think we changed that because it was unsound (I can’t remember why).
Then you get Class
for asking the type of a class (like Bool.class
). There’s a PR to change that so that typeof(Bool.class)
gives you Bool:Class:Class
but we are not sure it’s the right thing to do: https://github.com/crystal-lang/crystal/pull/7255
In your case you probably need to use the Bool.class | Int32.class
approach, but maybe showing some more code for what you want/need might be better.