Generic-user-small Victor Moroz 5 posts

Hello Dave,

Thanks for the screencast, it is great. Maybe some day you can dig into using @@ variables, especially on class level. It is used in ActiveRecord and is a bit tricky


felix = "felix" 

def felix.has_tail
  @@has_tail
end

def felix.has_tail=(tail)
  @@has_tail = tail
end

felix.has_tail = false
puts felix.has_tail     # false
tom = felix.clone
tom.has_tail = true
puts felix.has_tail     # true

class Cat
  def self.has_tail
    @@has_tail
  end
  def self.has_tail=(tail)
    @@has_tail = tail
  end
end

class Felix < Cat
end

class Tom < Cat
end

Tom.has_tail = true
Felix.has_tail = false
puts Tom.has_tail     # false


But this was the easy part. What I just barely understand


class Cat
  @@has_tail = true
  def self.has_tail
    @@has_tail
  end
end

puts Cat.has_tail  # true

def Cat.has_tail
  @@has_tail
end

puts Cat.has_tail  # uninitialized class variable @@has_tail in Object (NameError)


Guess it has something to do with ghost classes in the second case, so defining singleton within class def as self.method and as Class.method are quite different?

 
Generic-user-small Victor Moroz 5 posts

Same example with objects


class Cat
  def initialize
    @@has_tail = true
  end
  def has_tail
    @@has_tail
  end
  def has_tail=(tail)
    @@has_tail = tail
  end
end

felix = Cat.new
tom = Cat.new

puts felix.has_tail # true
puts tom.has_tail   # true

def tom.has_tail=(tail)
  @@has_tail = tail
end

tom.has_tail = false

puts felix.has_tail  # true
puts tom.has_tail    # true !!!

def tom.has_tail
  @@has_tail
end

puts tom.has_tail    #false

So it looks like @@var is relative to the place where method is actually defined. If we have ghost class and method is defined in the ghost class as with def tom.has_tail, then @@has_tail will be stored in the ghost class, but if methods defined in the class definition itself, then @@has_tail is stored in the class itself. And Ruby will not check superclass of this ghost class for @@var defined there, that is why previous example failed with ‘uninitialized class variable’ – inheritance does not work here. But previous example (with Cat.has_tail) is much more tricky – actually ‘class’ of class Cat should point to ‘Class’ and @@var should be stored there, but this is not what happens! In this case we would have @@has_tail defined in any class and this is not the case. Does it mean we have actually two ghost classes between Cat and Class?

2 posts, 1 voice