Domanda

You can create instance variables of a class and define their accessors as singleton methods of that class. But class variables like @@var behave strangely, especially when inherited. Are there any use cases of it?

È stato utile?

Soluzione

I interpret what you mean by strange as the fact that class variables are not different among each class but are shared among the inheritance hierarchy of classes.

As you mention and is also pointed out in Jörg W Mittag's answer to this question, it you wanted a variable to be consistent withing a class but differ outside of the class, then you can use a class instance variable on that class. That means, class variables should behave differently from that if it has any reason to exist. And class variables are indeed shared among classes within the inheritance hierarchy.

class A
  @@foo = 3
end
class B < A
  puts @@foo
end
# => 3

Probably, it may be useful when you want to share something that are common to classes in the hierarchy. For example, suppose you have some feature in a class that would be used in the classes that inherit this class. Suppose that that feature is dependent on a parameter, and you want that parameter change to be consistent among the classes that inherit that feature. Then, class variable will be useful.

For example, suppose you have this method:

class Array
  def join_with_delimiter
    join(@@delimiter)
  end
end
class A < Array; end

By setting @@delimiter once, you can expect consistent behavior across Array and A.

class Array; @@delimiter = "*" end
Array.new([:a, :b, :c]).join_with_delimiter # => "a*b*c"
A.new([:a, :b, :c]).join_with_delimiter # => "a*b*c"

class A; @@delimiter = "#" end
Array.new([:a, :b, :c]).join_with_delimiter # => "a#b#c"
A.new([:a, :b, :c]).join_with_delimiter # => "a#b#c"

If you do that with a class instance variable, you would not get consistent behavior:

class Array
  def self.delimiter; @delimiter end
  def join_with_delimiter
    join(self.class.delimiter)
  end
end
class A < Array; end

class Array; @delimiter = "*" end
Array.new([:a, :b, :c]).join_with_delimiter # => "a*b*c"
A.new([:a, :b, :c]).join_with_delimiter # => "abc"

class A; @delimiter = "#" end
Array.new([:a, :b, :c]).join_with_delimiter # => "a*b*c"
A.new([:a, :b, :c]).join_with_delimiter # => "a#b#c"

Altri suggerimenti

Class variables are used for passing values to different methods inside a class.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top