Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Instance variable initialization in Ruby

I think I'm going a bit crazy when trying to understand instance variables in Ruby. My only aim here is to make sure that every object created for a given class has a variable with a predetermined value without writing an initialize method for that class. Something like:

class Test

  @my = []

  attr_accessor :my

end
t = Test.new
t.my # I want [] but this shows nil

Is it possible to achieve this without touching initialize ? Thanks.

EDIT: To clarify, I'm writing some piece of code which will be executed similar to attr_accessor in the sense that it'll add an instance variable to the class in which it is executed. If I write my own initialize, I will end up clobbering the one written by the user.

like image 931
sasuke Avatar asked Mar 03 '12 19:03

sasuke


People also ask

How do you declare an instance variable in Ruby?

The ruby instance variables do not need a declaration. This implies a flexible object structure. Every instance variable is dynamically appended to an object when it is first referenced. An instance variable belongs to the object itself (each object has its own instance variable of that particular class)

How do you initialize an instance variable?

Normally, you would put code to initialize an instance variable in a constructor. There are two alternatives to using a constructor to initialize instance variables: initializer blocks and final methods. The Java compiler copies initializer blocks into every constructor.

What's an instance variable in Ruby?

In the Ruby programming language, an instance variable is a type of variable which starts with an @ symbol. Example: @fruit. An instance variable is used as part of Object-Oriented Programming (OOP) to give objects their own private space to store data.

Why do we initialize variables in Ruby?

The initialize method is useful when we want to initialize some class variables at the time of object creation. The initialize method is part of the object-creation process in Ruby and it allows us to set the initial values for an object.


2 Answers

What you are doing is defining an instance variable on the class level (Since classes are instances of the Class class, this works just fine).

And no, there is no way around initialize.

Edit: You have a little misconception in your edit. attr_accessor doesn't add an instance variable to the class. What it does, literally, is this (using your example of my):

def my; @my; end
def my=(value); @my = value; end

It doesn't actively create/initialize any instance variable, it just defines two methods. And you could very well write your own class method that does similar things, by using define_method.

Edit 2:

To further illustrate how one would write such a method:

class Module
  def array_attr_accessor(name)
    define_method(name) do
      if instance_variable_defined?("@#{name}")
        instance_variable_get("@#{name}")
      else
        instance_variable_set("@#{name}", [])
      end
    end

    define_method("#{name}=") do |val|
      instance_variable_set("@#{name}", val)
    end
  end
end


class Test
  array_attr_accessor :my
end

t = Test.new
t.my # => []
t.my = [1,2,3]
t.my # => [1, 2, 3]
like image 136
Dominik Honnef Avatar answered Oct 21 '22 11:10

Dominik Honnef


# as instance variable without initialize
class Test1
  def my; @my ||= [] end

  attr_writer :my
end

t = Test1.new
t.my


# as class instance variable
class Test2
  @my = []

  class << self; attr_accessor :my end
end

Test2.my
like image 40
Selman Ulug Avatar answered Oct 21 '22 12:10

Selman Ulug