What’s the difference between creating a method and a block in a Ruby class?

Asked

Viewed 119 times

2

I have a habit of creating methods like this in Ruby:

class MinhaClasse

  def metodo
    # meu método
  end

end

But sometimes we find around the direct creation of a code block in the class:

class MinhaClasse

  bloco do
    # meu bloco
  end

end

What is the point of this? What is the difference between this and the creation of a method? When and why should it be used?

1 answer

3


class MinhaClasse
  def metodo
    # meu método
  end
end

What is happening here is quite simple: You are creating an instance method in the class MinhaClasse. Nothing out of the ordinary.

class MinhaClasse
  outro_metodo
end

Already when you write this, is calling the method outro_metodo in the object self of the context. In this case, the self within the scope of the class is the class itself. This is equivalent to doing MinhaClasse.outro_metodo.

This method could have been defined thus:

def MinhaClasse.outro_metodo
  # código
end

Or so, in an equivalent way:

class MinhaClasse
  def self.outro_metodo
    # código
  end
end

Of course, like any other method invocation, you can pass a block, and the implementation can do whatever you want with the block, including defining an instance method using the last block as its implementation. Something like that:

class MinhaClasse
  def self.criar_metodo(&bloco)
    define_method(:metodo, &bloco)
  end

  criar_metodo do
    puts "oi!"
  end
end

obj = MinhaClasse.new
obj.metodo #=> "oi!"

Here I used the define_method, which is a class method Class to define methods from a block. One can even argue that def metodo(a, b) ... end is a mere syntactic sugar for define_method(:metodo) do |a, b| ... end.

As for usage, metaprogramming! This allows you to create "special" behavior syntax, and make the language behave as you wish. For example:

class MyButton < Button
  on :click do
    puts "Me clicou!"
  end
end

That could be implemented as:

def Button.on(event, &handler)
  @@callbacks ||= {}
  @@callbacks[event] ||= []
  @@callbacks[event] << handler
end

Or even:

def Button.on(event, &handler)
  define_method("on_" + event, &handler)
end
  • Good explanation. Sanou my doubts. Thanks!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.