Home > Net >  How to access property of class instance passed to the constructor of another class
How to access property of class instance passed to the constructor of another class

Time:10-15

coming from the .net world and making my very first steps in Ruby. This should be pretty straightforward but still I am missing something:

class TestClass

  def initialize(foo_class)
    puts foo_class.number
  end
end


class FooClass
  @number = 3

  attr_accessor :number
end

foo_class = FooClass.new
test_class = TestClass.new(foo_class)

I would expect the number 3 to show up in the output but instead it's null. But I have defined @number with just one @ to make sure it's an instance variable, so it should be attached to the instance I am passing to the constructor of TestClass. What am I missing?

CodePudding user response:

Instance variables belong to instances. That’s why they are called instance variables. You have two instance variables here, both of which are called @number, which belong to two different instances.

One belongs to FooClass. This one is initialized to 3. Another one belongs to foo_class. This one is never assigned to, hence it is uninitialized and thus evaluates to nil.

If you want it to have a specific value, you need to actually assign it one: you defined an attribute writer method, but you never call it:

foo_class.number = 4

Now, the instance variable @number of foo_class is initialized to 4.

If you don't want to force your users to remember to initialize the instance variable themselves, you can use an initializer method. Note that initializer methods are nothing special, they are methods just like any other method.

However, most objects are created by calling the Class#new factory method, which looks something like this:

class Class
  def new(...)
    obj = allocate
    obj.initialize(...)
    obj
  end
end

As you can see, the default implementation of Class#new calls an instance method called initialize on the newly created instance, which means you can customize the initialization by overriding #initialize:

class FooClass
  @number = 3

  attr_accessor :number

  def initialize
    self.number = 4
  end
end

Now, it is guaranteed that the instance variable @number of any instance of FooClass will always be initialized to 4 (at least when users use the default Class#new factory method).

  • Related