The Crystal Programming Language Forum

How to get concrete class name from the parent?

Hello,

I want to define a logger in a parent class to avoid having to redefine it in all child classes. However in the logs I see the name of the parent class not the child class.

Please, someone know how to get the concret class from a parent class?

Example:

It’s Parent displayed, not Child.

I have tried with {{ @type.subclasses.last }} but it does not seem to work on a multi-level hierarchy.

Here you go:

require "log"

abstract class Parent
  Log = ::Log.for self

  macro inherited
    Log = ::Log.for self

    def log
      Log
    end
  end

  def initialize
    log.info { "hello" }
  end

  def foo
    log.info { "foo" }
  end
end

class Child < Parent
end

class Deep < Child
end

Child.new.foo
Deep.new.foo

Note that I needed to define a method log inside each type. The reason is that if we just use the base methods referring to Log, these are statically bound to the type where they are used (Parent).
That is, when you write SomeType in a method, it will always point to the type resolved in that method, never in a child. (this is the same as in Ruby)

1 Like

Oh well done! Thanks for the solution and the explanations.

To limit intermediate definitions, I added this (it works well):

macro inherited
      {% unless @type.abstract? %}
        Log = ::Log.for self
      {% end %}
end
1 Like