My goal was to have a class with an instance variable typed to MyParentType(T).class. This works fine when the class is the same as MyParentType but starts to break down once you introduce a parent type, whether that be an abstract parent class, or a module.
https://play.crystal-lang.org/#/r/86j2
module Parent(T)
end
class Foo(T)
include Parent(T)
end
class Bar(T)
include Parent(T)
end
class Wrapper(T)
def initialize(@foo : Parent(T).class); end
end
pp Wrapper.new Foo(Int32)
# Error: instance variable '@foo' of Wrapper(Int32) must be Parent(Int32).class, not Foo(Int32).class
https://play.crystal-lang.org/#/r/86j3
abstract class Parent(T)
end
class Foo(T) < Parent(T)
end
class Bar(T) < Parent(T)
end
class Wrapper(T)
def initialize(@foo : Parent(T).class); end
end
pp Wrapper.new Foo(Int32)
# Error: instance variable '@foo' of Wrapper(Int32) must be Parent(T)+.class, not Foo(Int32).class
I'm assuming this is a bug related to generics?
I'm assuming this is a bug related to generics?
I don't think so, this fails too with a similar error.
I guess we didn't think of that use case...
module Parent
end
class Foo
include Parent
end
class Bar
include Parent
end
class Wrapper
def initialize(@foo : Parent.class); end
end
pp Wrapper.new Foo
Oh, actually, it's not a bug. When a class includes a module, the class inherits the module but the metaclass doesn't inherit the module's metaclass. That's why if you define a def self. method in the module it's not callable from an including class.
I still think we should drop extend from the language, and includeshould just add a parent into the class' and metaclass' hierarchy.
I don't think this will be fixed until we make a decision on how to model all of this.
But for the generic case it is a bug.
@asterite 馃憤, should I create another issue for the module one and keep this one scoped to the class issue?
The module one is not a bug, so I'm not sure...
@asterite Sorry I meant more so to represent the idea of removing extend, or is there an issue already tracking that?
It's just a thought or I wish I have, no concrete plans or design yet so I wouldn't open an issue for it.
Most helpful comment
Oh, actually, it's not a bug. When a class includes a module, the class inherits the module but the metaclass doesn't inherit the module's metaclass. That's why if you define a
def self.method in the module it's not callable from an including class.I still think we should drop
extendfrom the language, andincludeshould just add a parent into the class' and metaclass' hierarchy.I don't think this will be fixed until we make a decision on how to model all of this.