I have been taught to declare my instance variables with def initialize
. I have been under the impression that I could declare instance variables only within my initialize
methods.
Nevertheless, I declared an instance variable @foo
outside my initialize
method, and made it work as I intended:
class FooBar
def initialize(bar)
@bar = bar
end
def foo_as_instance_var
@foo = @bar.split(' ')
@foo
end
end
x = "something wicked this way comes"
y = FooBar.new(x)
puts y.foo_as_instance_var
Why am I able to declare an instance variable outside of initialize
method? Since I can declare instance variables in any method, is there a best practices rule I should follow, regarding where to declare instance variables (i.e., declare them within initialize
) or does it not matter?
I have been taught to declare my instance variables with def initialize
Since initialize
is the first instance method call in an object's life cycle, you typically declare your instance variables right there in order to ensure properly initialized variables. It's also the first place I'd expect instance variables to be defined when reading code.
I have been under the impression that I could declare instance variables only within my initialize methods.
There's no such restriction. You can declare instance variable anywhere within your instance.
A common use is memoization:
class FooBar
def foo
@foo ||= expensive_operation
end
end
On the first call, this would evaluate expensive_operation
and assign the result to @foo
. On subsequent calls, @foo
is returned.
Another popular example is Rails which uses instance variables to pass data from the controller to its view:
class FooController < ApplicationController
def index
@foos = Foo.all
end
end
is there a best practices rule I should follow, regarding where to declare instance variables
It depends on their purpose (see above examples). As a general rule, declare them in a way that avoids undefined variables (nil
errors) and structure your code so it is easy to read / follow.
Just to add to Stefan's excellent answer
I have been taught to declare my instance variables with
def initialize
A common mistake that ruby newbies make is something like this:
class Person
@name = "John"
def introduce
puts "Hi, my name is #{@name}"
end
end
And then they wonder why their names are not printed. To make this work, one can set the variable @name
in the initializer, just as the instruction says.
Lets start with the biggest misnomer - in Ruby there is no separate step of declaring variables - Variables are declared as you set them.
What the difference? Look at Java for example:
public class Bicycle {
private int cadence;
private int gear;
private int speed;
public Bicycle(int startCadence, int startSpeed, int startGear) {
gear = startGear;
cadence = startCadence;
speed = startSpeed;
}
}
We have to declare all the instance variables before we set them in the initializer (Bicycle). The same code in Ruby reads:
class Bicycle
def initialize(cadence, speed, gear)
@cadence = cadence
@speed = speed
@gear = gear
end
end
There is no declaration - only assignment. Ruby will even let you access instance variables which have not been set without error.
irb(main):003:0> @not_set
=> nil
You can't do that (generally) in languages where variables must be defined*.
I have been taught to declare my instance variables with def initialize. I have been under the impression that I could declare instance variables only within my initialize methods.
Nonsense. You can assign instance variables anywhere. Its commonly done in everything from setters and mutators (methods that alter an object) to factory methods (class methods that return an instance) or anywhere that you are altering the state of an object.
class Book
def initialize(title, author)
@title = title
self.author = author # calls the setter.
end
# A factory method
def create_from_csv(filename)
# ...
end
# A very contrived setter
def author=(author)
@author = "#{author.forename.upcase}. #{author.surname}"
end
# a mutator
def out_of_print!
@out_of_print = true
@last_printed = Date.today
end
end
However the initialize
method is where you should handle initializing your objects (duuh) and is thus the obvious place to set initial values.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With