3

Given this code:

class Mammal
  @@class_name = "mammal"
  def self.class_name
    @@class_name
  end
end

class Dog < Mammal
  @@class_name = "dog"
  def self.class_name
    @@class_name
  end
end

Dog.class_name
# => dog
Mammal.class_name
# => dog

Why is this a feature of ruby? Seems like class variables follow a different scope than instance variables do for instances. Is a class variable's scope shared across its entire inheritance chain? If so, why is that? They are separate classes and should have scoped class variables, no? What am I missing?

Andrew Kim
  • 3,145
  • 4
  • 22
  • 42
  • Hello. You've asked a couple of related questions. One of those questions is an exact duplicate, which is why I just applied the so-called "dup hammer." The other, "why," is not an exact duplicate, although I suspect it's a tough question to find an answer for. For the most part, the answer is "that's the way it is, because the author of Ruby decided to make it so." If we were lucky enough to find something that Matz wrote about class variable behavior, then the "why" part could be answerable. – Wayne Conrad Oct 26 '16 at 13:52
  • 1
    Class variables are not only shared between a class and its subclasses, but also between a class and its instances. – Stefan Oct 26 '16 at 13:53
  • I should also add that `@@` class variables are almost never a good idea. Whenever I've worked with code that used them, I'm usually able to change them to class instance variables, which are easier to reason about. – Wayne Conrad Oct 26 '16 at 13:54
  • thanks @WayneConrad sorry for the duplicate, this makes sense – Andrew Kim Oct 26 '16 at 14:07
  • from the horses mouth https://twitter.com/yukihiro_matz/status/791300638592241664 : "consider these as global variables with limited scope." – Andrew Kim Oct 26 '16 at 15:48

1 Answers1

0

Class variables are shared throughout the class hierarchy, they are not inherited, so assignment order matters:

class Mammal
  @@class_name = "mammal"
  def self.class_name
    @@class_name
  end
end

class Dog < Mammal
  @@class_name = "dog"
  def self.class_name
    @@class_name
  end
end

class Mammal
  @@class_name = "fish"
end

Dog.class_name # fish
Mammal.class_name # fish

UPDATE

Use class instance variables instead, class variables are tricky:

class Mammal
  @class_name = "mammal"
  def self.class_name
    @class_name
  end
end

class Dog < Mammal
  @class_name = "dog"
  def self.class_name
    @class_name
  end
end

Dog.class_name # dog
Mammal.class_name # mammal
Victor Moroz
  • 9,167
  • 1
  • 19
  • 23