Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing an instance variable within the `initialize` method

Tags:

object

oop

ruby

Given this basic class in Ruby:

class TestClass
  def initialize(name)
    @name = name
  end
end

How do I then access the instance variable name directly from within the initialize method without creating a getter function? is this even possible? (i.e. using dot notation) or does the initialize method cease to exist once a class is instantiated, hence the need to define a getter method?

I think what I'm trying to ask is initialize a class or instance method?

like image 923
seeker Avatar asked May 23 '26 02:05

seeker


2 Answers

The "getter method" is defined so that you can use the variable from outside the class:

class TestClass
  attr_reader :name

  def initialize(name)
    @name = name
  end
end
# TestClass.new('Ben').name  # => 'Ben'

If you don't need to access it from outside the class, you can just use @name:

class TestClass
  def initialize(name)
    @name = name
  end

  def greet
    puts "Hello, %s" % @name
  end
end
# TestClass.new('Ben').greet # outputs: Hello, Ben

You can use the @name inside initialize:

class TestClass
  def initialize(name)
    @name = name
    puts "Name backwards: %s" % @name.reverse
  end
end
# TestClass.new('Ben') # outputs neB

Initialize is a special method, when you define initialize instance method, it is automatically marked private. The class method new calls it after creating an instance of your class.

Nothing stops you from calling private methods from inside the class:

class TestClass
  def initialize(name)
    @name = name
    puts "Name is now %s" % @name
  end

  def flip_name
    initialize(@name.reverse)
  end
end
# t = TestClass.new('Ben') # outputs "Name is now Ben"
# t.flip_name # outputs "Name is now neB"
# t.instance_variable_get(:@name) # => 'neB'

The flip_name method that calls initialize works just fine, but of course this is quite unconventional and almost never used, because it does not make much sense.

It's possible to call private methods from outside the class using send:

# t.send(:initialize, 'Bill') # outputs "Name is now Bill"
# t.instance_variable_get(:@name) # => 'Bill'

Without send, you get NoMethodError:

> t.initialize('Jack')
NoMethodError: private method `initialize' called for #<TestClass:0x00007fa2df8e4570>

Ruby 1.9 beta releases changed send to act like public_send does today, allowing access to only public methods and there was going to be funccall for calling private methods if you really want to, for unit testing purposes for example. I think it caused too much compatibility issues and the change was reverted.

So in conclusion, yes, you can call initialize again and it does not cease to exist, but it is almost never done because it makes very little sense. To access instance variables from inside the class, you use @ notation like @name, to access them from outside of the class, you define a getter.

like image 193
Kimmo Lehto Avatar answered May 26 '26 03:05

Kimmo Lehto


Yes, there is a way. But it's not a traditional one. It's more like querying the object to know

TestClass.new("foo").instance_variable_get(:@name)
=> "foo"

The initialize method does not "cease to exsist". It's executed, that's it. What your method do, in your case, is that the variable is set.

like image 31
Ursus Avatar answered May 26 '26 03:05

Ursus