The Crystal Programming Language Forum

Get super and ancestor class name

New to Crystal with years Ruby experience.

I could not find a way to get the super or ancestors of a class in Crystal. In ruby, we have superclass and ancestor methods. What are the equivalent in Crystal lang?

Thanks.

They also exist in crystal but are macro (compile time) level methods, i.e. you can’t get that information at runtime. See TypeNode.ancestors and TypeNode.superclass.

EDIT: Add an example

abstract class One; end
abstract class Two < One; end
class Three < Two; end

{{pp Three.superclass}} # => Two
{{pp Three.ancestors}} # => [Two, One, Reference, Object]

Thanks, Blacksmoke16. Very helpful.

But I am still not sure how to handle my use case. Essentially, I have an object, for which I want to return its ancestors. Something like:

a = MyCalss.new

ancestors = get_ancestors(a)

Based on the documentation, I tried the following, but I seemed to not able to get across the boundary of Macro and regular code:

macro add_describe_methods

def describe

"Class is: " + {{ @type.stringify }}

end

def self.describe

"Class is: " + {{ @type.stringify }}

end

def self.get_ancestors

"Ancestors are: " + {{@type.superclass}}

end

end

class Foo

add_describe_methods

end

a = Foo.new

pp a.describe # => this works

pp Foo.describe # => this works too

pp Foo.get_ancestors

The compiler complains:

Showing last frame. Use --error-trace for full trace.

There was a problem expanding macro ‘add_describe_methods’

Code in tmp.cr:16:3

16 | add_describe_methods

^

Called macro defined in tmp.cr:1:1

1 | macro add_describe_methods

Which expanded to:

8 |

9 | def self.get_ancestors

10 | "Ancestors are: " + Reference

^

Error: no overload matches ‘String#+’ with type Reference.class

Overloads are:

  • String#+(other : self)
  • String#+(char : Char)

How should I fix it? Thanks.

Use three backticks for code blocks like that next time, makes it a bit easier to read.

The error you’re seeing is just as it says, there is no method on String that allows you to add a Reference.class. Your options would be {{@type.superclass.stringify}} so the macro result is turned into a string. Or Just do like "Ancestors are: {{@type.superclass}}" to add the value directly into the string.

1 Like