Hello,
This code (https://carc.in/#/r/5whi):
class Foo
end
class Bar < Foo
end
ary = Array(Foo.class).new
ary << Bar
Compiles nicely, while when replacing class with module (https://carc.in/#/r/5whj):
module Foo
end
class Bar
include Foo
end
ary = Array(Foo.class).new
ary << Bar
It failes to compile with no overload matches 'Array(Foo:Module)#<<' with type Bar.class
.
Is that intended? Is that going to change?
Thanks,
2 Likes
I suspect what you’ve intended to write is:
https://play.crystal-lang.org/#/r/5wp0
module Foo
end
class Bar
include Foo
end
ary = Array(Foo).new
ary << Bar.new()
p! ary
No, I’m absolutely sure that I need to store classes, not their instances.
Probably not intended nor designed. I don’t recall any story about the metaclass design related to modules and classes that are including them.
What is what you are trying to achieve later with that array?
1 Like
There are two things here. First, it’s OK for the code not to compile because when you include a module only the instance type gets included, so technically the Bar
class is not a Foo
class. You can see this is like that because you can’t invoke class methods of Foo
from Bar
.
module Foo
def self.foo
1
end
end
class Bar
include Foo
end
Bar.foo # undefined method 'foo' for Bar.class
However, I think it should work when extending the module… but it doesn’t.
Also, as @bcardff says, all of this hasn’t been well defined yet.
1 Like
That’s interesting. However, even when extend
ing, it doesn’t work as well (Carcin):
module Foo
end
class Bar
extend Foo
end
ary = Array(Foo.class).new
ary << Bar
Error in line 9: no overload matches 'Array(Foo:Module)#<<' with type Bar.class
Overloads are:
- Array(T)#<<(value : T)
Nevertheless, my use-case is Event-Driven Architecture (EDA), where a number of subscribers can subscribe to an Event
. For performance benefit, it’s smart to store them in a Hash(Event.class, Array(Proc(Event, Nil))
for faster reaction times. Currently the code looks like this:
struct MyEvent < Event
getter foo
def initialize(@foo : String)
end
end
channel.subscribe(MyEvent) { |event| do_something(event.foo) }
It works nicely when Event
is abstract struct
, but I’d like to make it a module – just for more beautiful (subjectively) code.
Summing it up, Hash(Event.class, Proc(Event, Nil))
doesn’t work when Event
is a module, as well as Set(Event.class)
and Array(Event.class)
, as stated in the first post.
P.S: I managed to store Proc
s with abstract Event
in the hash as a pair of Void*
.
_P.P.S: For better understanding, I have a code sample for channel: https://gist.github.com/vladfaust/455b343f539188af43a91188d06a1a07_
Okay, as always, after posting I understand that module
would not work for me in my case because all_subclasses
for a module doesn’t make sense. And I need to know subclasses for my arch.
However, the issue still remains, and I cannot use a module Foo
's includer in the place of Foo.class
.
How about Array(Foo.module)
?