Bird
Raised Fist0
Rubyprogramming~7 mins

Define_method with closures in Ruby

Choose your learning style10 modes available
Introduction

Define_method with closures lets you create methods that remember values from their surrounding code. This helps make flexible and reusable methods.

When you want to create methods dynamically based on some data.
When you want methods to remember specific values without passing them every time.
When you want to avoid repeating similar methods with small differences.
When you want to keep related data and behavior together inside a method.
Syntax
Ruby
define_method(:method_name) do |parameters|
  # method body using parameters and closed-over variables
end

define_method creates a method with the given name.

The block passed to define_method can use variables from outside its scope (closures).

Examples
This example defines a method greet that remembers the instance variable @name using closure.
Ruby
class Greeter
  def initialize(name)
    @name = name
  end

  define_method(:greet) do
    "Hello, #{@name}!"
  end
end
This method multiply remembers the @factor and multiplies it with the input number.
Ruby
class Multiplier
  def initialize(factor)
    @factor = factor
  end

  define_method(:multiply) do |number|
    number * @factor
  end
end
The next method remembers and updates the @count variable each time it is called.
Ruby
class Counter
  def initialize(start)
    @count = start
  end

  define_method(:next) do
    @count += 1
  end
end
Sample Program

This program creates a Person class. It defines a method say_hello using define_method that remembers the person's name and returns a greeting.

Ruby
class Person
  def initialize(name)
    @name = name
  end

  define_method(:say_hello) do
    "Hi, my name is #{@name}."
  end
end

person = Person.new("Alice")
puts person.say_hello
OutputSuccess
Important Notes

Closures let the method remember variables like @name even after initialization.

Using define_method is useful for dynamic or repetitive method creation.

Be careful with variable scope to avoid unexpected results.

Summary

define_method creates methods dynamically with a block.

The block can use variables from outside, forming a closure.

This helps make flexible, reusable methods that remember data.

Practice

(1/5)
1. What does define_method do in Ruby?
easy
A. Defines a class variable
B. Deletes an existing method
C. Calls a method immediately
D. Creates a method dynamically using a block

Solution

  1. Step 1: Understand the purpose of define_method

    define_method is used to create methods dynamically at runtime using a block of code.
  2. Step 2: Compare with other options

    Options B, C, and D describe different actions unrelated to define_method.
  3. Final Answer:

    Creates a method dynamically using a block -> Option D
  4. Quick Check:

    define_method creates methods dynamically [OK]
Hint: Remember: define_method builds methods with blocks [OK]
Common Mistakes:
  • Thinking define_method calls methods
  • Confusing define_method with deleting methods
  • Assuming it defines variables
2. Which of the following is the correct syntax to define a method named greet using define_method that returns "Hello"?
easy
A. def define_method(:greet) "Hello" end
B. define_method greet { return "Hello" }
C. define_method(:greet) { "Hello" }
D. define_method(:greet, "Hello")

Solution

  1. Step 1: Recall correct define_method syntax

    The correct syntax uses a symbol for the method name and a block: define_method(:name) { ... }.
  2. Step 2: Check each option

    def define_method(:greet) "Hello" end uses def incorrectly. define_method greet { return "Hello" } lacks symbol (greet undefined). define_method(:greet, "Hello") passes string instead of block. B matches correct syntax.
  3. Final Answer:

    define_method(:greet) { "Hello" } -> Option C
  4. Quick Check:

    Correct syntax uses symbol and block [OK]
Hint: Use symbol and block for define_method syntax [OK]
Common Mistakes:
  • Using method name without symbol
  • Incorrect block syntax
  • Using def inside define_method
3. What will be the output of this Ruby code?
class Person
  def initialize(name)
    @name = name
    self.class.define_method(:greet) { "Hello, #{@name}!" }
  end
end

p = Person.new("Alice")
puts p.greet
medium
A. Hello, Alice!
B. Hello, !
C. NoMethodError
D. SyntaxError

Solution

  1. Step 1: Understand closure and instance variable scope

    The block passed to define_method defines the method body. However, the string interpolation "Hello, #{@name}!" is evaluated immediately when define_method is called, not when the method is invoked. At that time, @name is nil because the block is defined in the class context, not the instance context.
  2. Step 2: Predict output

    Therefore, the method greet returns the string with @name interpolated as nil, resulting in "Hello, !".
  3. Final Answer:

    Hello, ! -> Option B
  4. Quick Check:

    String interpolation in define_method block evaluated immediately [OK]
Hint: String interpolation in define_method block is evaluated immediately [OK]
Common Mistakes:
  • Thinking @name is dynamically resolved inside the block
  • Expecting 'Hello, Alice!' due to misunderstanding of closure
  • Confusing instance and class scope
4. Identify the error in this code snippet:
class Calculator
  def initialize(x)
    @x = x
    self.class.define_method(:square) { @x * @x }
  end
end

calc = Calculator.new(4)
puts calc.square
medium
A. No error, outputs 16
B. Syntax error in define_method block
C. The block does not capture @x correctly, causing nil * nil error
D. The method square is not defined for instances

Solution

  1. Step 1: Analyze where define_method is called

    define_method on self.class defines an instance method square. The block executes in instance context.
  2. Step 2: Understand closure and instance variable scope

    @x resolved on instance: 4 * 4 = 16. No capture issue, no error.
  3. Final Answer:

    No error, outputs 16 -> Option A
  4. Quick Check:

    Instance vars work in class-level define_method [OK]
Hint: Instance vars work in class-level define_method blocks [OK]
Common Mistakes:
  • Thinking method undefined for instances
  • Expecting syntax error
  • Believing nil * nil error from poor capture
5. How can you fix this code so that each instance of Person has a greet method that correctly uses its own @name?
class Person
  def initialize(name)
    @name = name
    self.class.define_method(:greet) { "Hello, #{@name}!" }
  end
end

p1 = Person.new("Bob")
p2 = Person.new("Carol")
puts p1.greet
puts p2.greet
hard
A. Define greet method inside initialize using define_singleton_method
B. Use self.class.define_method but pass @name as parameter
C. Move @name to a class variable
D. Use def greet; "Hello, #{@name}!"; end inside initialize

Solution

  1. Step 1: Understand the problem with class-level define_method

    Class-level define_method in initialize redefines a shared instance method each time (inefficient, problematic for local var closures). Instance vars work via dynamic lookup.
  2. Step 2: Use define_singleton_method to define method per instance

    define_singleton_method defines on the instance's singleton class, giving each its own greet accessing own @name.
  3. Final Answer:

    Define greet method inside initialize using define_singleton_method -> Option A
  4. Quick Check:

    Use define_singleton_method for per-instance closures [OK]
Hint: Use define_singleton_method for instance-specific methods [OK]
Common Mistakes:
  • Trying to pass instance vars as parameters to class method
  • Using class variables instead of instance variables
  • Defining method with def inside initialize incorrectly
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard