I'm trying to write a method that returns an array of subclasses (the actual class, not the string). I have it working, but I think this is a bit of a hack.
The class variable @@subclasses gets typed properly when I instantiate it with the Animal class, and works as you can see by the output. But I also have to shift the array to remove the abstract class. It seems I should be able to do something like @@subclasses = [] of Animal though this would just be an array of instances, not classes. Is there a special grammar for types of this sort?
```crystal
abstract class Animal
@@subclasses = [Animal] # specified manually!
@@subclasses.shift # drop the class leaving the array properly typed and empty
def self.subclasses
@@subclasses
end
macro inherited
Animal.subclasses << {{@type.name}}
end
end
class Dog < Animal
end
class Cat < Animal
end
class Terrier < Dog
end
Animal.subclasses # [Dog, Cat, Terrier] : Array(Animal)
Animal.subclasses[0].new #
Yeah, there's Crystal::Macros::TypeNode#subclasses.
abstract class Animal; end
class Dog < Animal; end
class Cat < Animal; end
class Terrier < Dog; end
# print all subclasses
pp {{ Animal.all_subclasses }} # => [Dog, Terrier, Cat]
# print only direct subclasses
pp {{ Animal.subclasses }} # => [Dog, Cat]
Thank you!
Most helpful comment
Yeah, there's
Crystal::Macros::TypeNode#subclasses.