0
class Var
  @instance_variable = "instance variable"
  @@class_instance_variable = "class instance variable"

  def self.class_method
    puts @instance_variable
    puts @@class_instance_variable
  end

  def instance_method
    puts @instance_variable
    puts @@class_instance_variable
  end

end 

The class method has access to both class instance and instance variables. But the instance method has just access to class instance variable. @instance_variable is nil inside instance method. What is the logical explanation behind this?

Var.class_method #=> "instance variable" "class instance variable"
Var.new.instance_method #=> "class instance variable" nil 

And is it correct that the instance variables dont get inherited by child classes? Why is that?

Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
mhaseeb
  • 1,739
  • 2
  • 12
  • 24
  • _Sidenote_: `nil` in shown result of `Var.new.instance_method` execution is confusing, since it a) should appear before "class instance variable" and b) won’t appear at all in `puts`. – Aleksei Matiushkin Mar 04 '16 at 06:52
  • It goes as follows. (You must replace my (@) with @, as ampersands begin SO usernames and SO only permits one per comment.) `class A; (@)(@)class_variable = 1; (@)class_instance_variable = 2; def my_method; (@)instance_variable = 3; end; end` – Cary Swoveland Mar 04 '16 at 06:56
  • @FrederickCheung I disagree that this is a duplicate. OP in fact asks “`@instance_variable` is nil inside instance method. What is the logical explanation behind this?” It was induced by the fact OP misunderstands the notion of instance variable scoping at all. – Aleksei Matiushkin Mar 04 '16 at 07:17
  • Your question is wrong.. @@ is a class variable. not what you labelled it, you got that wrong every time you wrote @@var. The variable you put at the top with @ is a class instance variable, so you didn't label that one well. And the other @var instance variables you labelled ok. – barlop May 24 '18 at 13:28

3 Answers3

1

Inside class Var (not Class Var!), as well as inside the class method, self is Var, self.class is Class. Inside def instance_method, self.class is Var. The class variable is designed to be there; but the instance variable is defined on Var as an instance of Class class. If you have v = Var.new, then @instance_variable is looking at the @instance_variable on v, which is not there.

No, variables are never inherited; only methods are. Variables represent object state, and are specific to each object; inheritance is a relationship between two classes.

Amadan
  • 191,408
  • 23
  • 240
  • 301
1

In fact, you have not defined instance variable on Var’s instance at all.

▶ Var.class_variables
#⇒ [:@@class_instance_variable]
▶ Var.instance_variables
#⇒ [ :@instance_variable ]
▶ Var.new.instance_variables
#⇒ []

What you have defined, are: class variable on Var and class instance variable on Var, an instance of Class class. This is because you have it declared in class scope.

To define an instance variable on Var’s instance, one should call @iv from the respective scope, namely—from inside one of the instance methods of Var:

▶ class Var
▷   def iv
▷     @iv ||= 42
▷   end
▷​ end
▶ Var.new.instance_variables
#⇒ []
# the above is because instance variables are lazily instantiated
▶ v = Var.new
▶ v.iv
#⇒ 42
▶ v.instance_variables
#⇒ [ :@iv ]
Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
0

A class variable is shared among a class, its instances, subclasses, and their instances.

An instance variable takes scope only within a single instance. When undefined, it returns nil as a language design.

sawa
  • 165,429
  • 45
  • 277
  • 381