Class methods invocation works unexpectedly

Hi Crystal community,

Just discovered Crystal a week or so ago - fascinating thing!

I have this issue to sort out: calling class methods within the scope of the class works only with a fully qualified name AClass.a_method. I would expect (and I believe the docs are saying) that within the scope of the unit (class or module) one can call static methods with self.a_static_method … no? What am I missing?

An example follows:

class AClass
  def initialize(@name : String)

  def this_fails
    # Error: undefined method 'class_method' for AClass

  def this_also_fails
    # Error: undefined method 'class_method' for AClass

  def this_works

  def self.class_method(name : String) : Nil
    puts "class_method called with name=#{name}"

ac = "Bimbo"

Any help would be much appreciated, thank you!

self in the context of an instance method is referring to the instance itself, which is a different scope compared to the class scope the class methods are defined in. The idiomatic way would be to do like self.class.class_method @name, which is an easy way to get a reference to the current instance’s class scope.

The docs could perhaps be clearer, but when it says

When called from within the same class or module scope the receiver can be self or implicit

then the scopes referred to are regions with the same self. self within an instance method refers to instances of the class. self within a class method refer to the class itself. Hence the behavior you are seeing show up.

This behavior is shared with Ruby, for example.

1 Like

@Blacksmoke16, @yxhuvud: thank you so much!

I get it now. (You could probably sense my python background ;)

For people like me, an example in the documentation including the self.class.class_method approach might be of help. (I wonder if it makes sense to try contributing something to that page?)

1 Like