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).