6

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?

8
  • 3
    Doesn't matter. Do what makes sense. You were under the wrong impression if you think it should only happen in initialize. Read this for more info on use of instance variables outside initialize. Commented Jan 15, 2019 at 4:25
  • @anothermh I was. And the question was definitely lingering at the back of my head... Commented Jan 15, 2019 at 4:27
  • To be able to access across instance methods, that is the whole point of instance variables. Commented Jan 15, 2019 at 5:05
  • @anothermh lol, I literally forgot or missed attr_accessor. Thanks! Commented Jan 15, 2019 at 5:42
  • 1
    If you were only allowed to assign to instance variables inside initialize, then you could never, ever change them, except by calling initialize again. Who told you that? Also, initialize is just a method like any other method, so if you weren't allowed to assign to instance variables in methods, then you couldn't assign them in initialize either. The fact that you can assign them in initialize already proves that you can assign them in methods, because initialize is a method. This entire statement makes no sense. Commented Jan 16, 2019 at 18:12

3 Answers 3

10

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.

Sign up to request clarification or add additional context in comments.

Comments

6

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.

Comments

3

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.

2 Comments

* well unless you are talking about Javascript which is a very special snowflake.
"access instance variables which have not been set without error" – there will be a warning, though (if enabled).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.