Special cased?

This confused me a bit

class A
@a = 2
@@a = 3
def self.a
   puts [@a, @@a]
end
end

class B < A; end

A.a # [2, 3]
B.a # [nil, 3]

shouldn't @a just lookup @@a in the parent? Different treatment for
different types of variables?

-r

···

--
Posted via http://www.ruby-forum.com/.

When you write:

  class A
    @a = 2

take into account that @a=2 is just parsed when loading class A for first
time.
When you later do "class B < A; end", the Ruby interpreter doesn't read the
line "@a = 2" again as it already parsed class A and just stored in memory the
methods of class A.

···

El Sábado, 19 de Diciembre de 2009, Roger Pack escribió:

This confused me a bit

class A
@a = 2
@@a = 3
def self.a
   puts [@a, @@a]
end
end

class B < A; end

A.a # [2, 3]
B.a # [nil, 3]

shouldn't @a just lookup @@a in the parent? Different treatment for
different types of variables?

--
Iñaki Baz Castillo <ibc@aliax.net>

Roger Pack wrote:

shouldn't @a just lookup @@a in the parent?

Nope - class variables (@@) have nothing to do with instance variables
(@). @a in this case is just an instance variable of the class object,
so @a in class B is different to @a in class A

Class variables are a very strange beast with bizarre semantics. I would
avoid them if I were you.

···

--
Posted via http://www.ruby-forum.com/\.

Hi --

···

On Sat, 19 Dec 2009, Roger Pack wrote:

This confused me a bit

class A
@a = 2
@@a = 3
def self.a
  puts [@a, @@a]
end

class B < A; end

A.a # [2, 3]
B.a # [nil, 3]

shouldn't @a just lookup @@a in the parent? Different treatment for
different types of variables?

I think you mean shouldn't it just look up @a (not @@a) in the parent
-- and the answer is no :slight_smile: A and B are different objects, and
therefore do not share instance variables.

David

--
David A. Black
Senior Developer, Cyrus Innovation Inc.
THE COMPLEAT RUBYIST, Ruby training with Black/Brown/McAnally!
January 22-23, Tampa, Florida
Info and registration at http://www.thecompleatrubyist.com

> This confused me a bit
>
> class A
> @a = 2
> @@a = 3
> def self.a
> puts [@a, @@a]
> end
> end
>
> class B < A; end
>
> A.a # [2, 3]
> B.a # [nil, 3]
>
> shouldn't @a just lookup @@a in the parent? Different treatment for
> different types of variables?

When you write:

  class A
    @a = 2

take into account that @a=2 is just parsed when loading class A for first
time.
When you later do "class B < A; end", the Ruby interpreter doesn't read the
line "@a = 2" again as it already parsed class A and just stored in memory
the methods of class A.

Take a look to this example which shows the same concept:

  > class A
         puts "I'm A"
       end
  I'm A
  nil

  > class B < A; end
  nil

···

El Sábado, 19 de Diciembre de 2009, Iñaki Baz Castillo escribió:

El Sábado, 19 de Diciembre de 2009, Roger Pack escribió:

--
Iñaki Baz Castillo <ibc@aliax.net>

Hi --

This confused me a bit

class A
@a = 2
@@a = 3
def self.a
   puts [@a, @@a]
end
end

class B < A; end

A.a # [2, 3]
B.a # [nil, 3]

shouldn't @a just lookup @@a in the parent? Different treatment for
different types of variables?

When you write:

class A
   @a = 2

take into account that @a=2 is just parsed when loading class A for first
time.
When you later do "class B < A; end", the Ruby interpreter doesn't read the
line "@a = 2" again as it already parsed class A and just stored in memory the
methods of class A.

Also, instance variables are always pegged to "self".

   class A
     puts self # A
     @x = 1
   end

   class B < A
     puts self # B
     puts @x # nil
   end

Every object, including every Class object, has its own supply of
instance variable "slots", and the meaning of @var is always
self.instance_variable_get("@var").

David

···

On Sat, 19 Dec 2009, Iñaki Baz Castillo wrote:

El Sábado, 19 de Diciembre de 2009, Roger Pack escribió:

--
David A. Black
Senior Developer, Cyrus Innovation Inc.
THE COMPLEAT RUBYIST, Ruby training with Black/Brown/McAnally!
January 22-23, Tampa, Florida
Info and registration at http://www.thecompleatrubyist.com

class A
    @a = "hello"
    
    def self.say
      puts defined?(@a).inspect
    end
  end

  A.say
  => "instance-variable"
  nil

  class B < A ; end

  B.say
  nil
  nil

But as I already explained, the line '@a = "hello"' is just parsed by Ruby
interpreter when loading class A.

When creating class B (which inherits from A) the Ruby parser doesn't read the
whole class A definition again. Instead it already has in memory all the
class/instance methods defined for class A so it wouldn't read '@a = "hello"'
anymore.

And because of it, B class object doesn't know @a as its instance variable, it
knows nothing about @a.

···

El Sábado, 19 de Diciembre de 2009, David A. Black escribió:

I think you mean shouldn't it just look up @a (not @@a) in the parent
-- and the answer is no :slight_smile: A and B are different objects, and
therefore do not share instance variables.

--
Iñaki Baz Castillo <ibc@aliax.net>

Class variables are a very strange beast with bizarre semantics. I would
avoid them if I were you.

Yeah they must be special cased so that beginning users can use them
with abandon and it will "just work."

Interesting.

in
class A
@@a = 3
end

class B < A
def go
   @@a
end
end

in B.new.go => 3...where is @@a stored?...it's not in B...it's not in
A's nearest ancestor, which is "Object"...it's special cased somehow?

Roughly paraphrasing a quote I heard once...
"after using ruby for 5 years, it is still surprising to me" (no offence
intended, of course :slight_smile:
Cheers.
-r

···

--
Posted via http://www.ruby-forum.com/\.

Hi --

I think you mean shouldn't it just look up @a (not @@a) in the parent
-- and the answer is no :slight_smile: A and B are different objects, and
therefore do not share instance variables.

class A
   @a = "hello"

   def self.say
     puts defined?(@a).inspect
   end
end

A.say
=> "instance-variable"
nil

class B < A ; end

B.say
nil

Exactly :slight_smile:

But as I already explained, the line '@a = "hello"' is just parsed by Ruby
interpreter when loading class A.

When creating class B (which inherits from A) the Ruby parser doesn't read the
whole class A definition again. Instead it already has in memory all the
class/instance methods defined for class A so it wouldn't read '@a = "hello"'
anymore.

And because of it, B class object doesn't know @a as its instance variable, it
knows nothing about @a.

The general rule about instance variables (that they are strictly
per-object) is still in effect, though, even if you do it some other
way:

   class A
   end

   class B < A
   end

   A.instance_variable_set("@a", "hello")
   p B.instance_variable_get("@a") # nil

David

···

On Sun, 20 Dec 2009, Iñaki Baz Castillo wrote:

El Sábado, 19 de Diciembre de 2009, David A. Black escribió:

--
David A. Black
Senior Developer, Cyrus Innovation Inc.
THE COMPLEAT RUBYIST, Ruby training with Black/Brown/McAnally!
January 22-23, Tampa, Florida
Info and registration at http://www.thecompleatrubyist.com

Roger Pack wrote:

class A
@@a = 3
end

class B < A
def go
   @@a
end
end

in B.new.go => 3...where is @@a stored?...it's not in B...it's not in
A's nearest ancestor, which is "Object"...it's special cased somehow?

I believe it's picking up the value from class A, since that's B's
ancestor, and B doesn't already have an @@a of its own.

It gets scarier though. Have a look at this:

class A
  def a
    @@a
  end
  def a=(v)
    @@a = v
  end
end

=> nil

class B < A
  def a2
    @@a
  end
  def a2=(v)
    @@a = v
  end
end

=> nil

ai = A.new

=> #<A:0x7f59fb532260>

bi = B.new

=> #<B:0x7f59fb52cbf8>

bi.a2 = 1

=> 1

ai.a

NameError: uninitialized class variable @@a in A
  from (irb):3:in `a'
  from (irb):23

bi.a

NameError: uninitialized class variable @@a in A
  from (irb):3:in `a'
  from (irb):24

bi.a2

=> 1

bi.a = 2

=> 2

ai.a

=> 2

bi.a

=> 2

bi.a2

=> 1

ai.a = 3

=> 3

ai.a

=> 3

bi.a

=> 3

bi.a2

=> 1

So which 'version' of the @@a class variable you see, depends on where
the method which reads it was defined... or something like that.

···

from :0
  from :0
--
Posted via http://www.ruby-forum.com/\.

Hi --

Class variables are a very strange beast with bizarre semantics. I would
avoid them if I were you.

Yeah they must be special cased so that beginning users can use them
with abandon and it will "just work."

See this, from Matz:

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/347355

especially:

  (3) and lastly, and most importantly, do not use class variables,
      unless you really really need them; they are fundamentally global
      variables.

That's the thing; they're really hierarchy globals, but confusingly
similar to instance variables (of which they are essentially the
opposite) in appearance.

David

···

On Sun, 20 Dec 2009, Roger Pack wrote:

--
David A. Black
Senior Developer, Cyrus Innovation Inc.
THE COMPLEAT RUBYIST, Ruby training with Black/Brown/McAnally!
January 22-23, Tampa, Florida
Info and registration at http://www.thecompleatrubyist.com