When do I have to use self before a variable/method of class name?

Hi, I just started learning the crystal language and it’s not clear to me when to use self (maybe I missed something in docs).
I wrote a simple program in which I added inheritance from GTK::Button in the descendant constructor I would like to set the label value. According to the documentation it is a function - button docs. So why do I need to add self.label="text"instead of use simply label="text" in this case?

Full source code:

require "gtk4"

class MyButton < Gtk::Button
  def initialize
    super()
    self.label = "My button title"
    #label = "My button title" - not working
  end
end  

app = Gtk::Application.new("hello.example.com", Gio::ApplicationFlags::None)
count = 0

app.activate_signal.connect do
  window = Gtk::ApplicationWindow.new(app)
  window.title = "Hello World!"
  window.set_default_size(200, 200)

  hbox = Gtk::Box.new(Gtk::Orientation::Horizontal, 10)
  hbox.spacing = 1

  button = Gtk::Button.new_with_label("Hello!!")
  button.clicked_signal.connect do
    count += 1
    button.label = "You clicked #{count} times!"
  end

  hbox.append(button)

  mybutton = MyButton.new()
  hbox.append(mybutton)
  
  window.child = hbox
  window.present
end

exit(app.run)

When I change self.label to label it is not working.

Without the self. prefix, you’re making a local variable called label whereas the self. forces it to call the Gtk::Button#label= method. In this particular case it would prob be easiest to just do super label: "My button title" and not deal with trying to call the setter.

Usually the self. prefix is optional, but there are cases, like this one, where it is required in order to get the behavior you want. I personally always use it just so its more clear what are methods calls versus simple local variables. E.g. some_var = label vs some_var = self.label. The latter removes all doubt if label is another local variable, or a method/macro.

2 Likes

OK, now it’s clear to me. Using = creates local variable also when there is setter with that name. Thanks for the clarification.

It can be hard bug to find in code, so is there a compiler option to show warning or hint in that cases?

No, the compiler has no way to know if you are intending to create a local variable or call a method with that same name.