Class variables in Ruby

I gave the following example from this tutorial :

class Song @@plays = 0 def initialize(name, artist, duration) @name = name @artist = artist @duration = duration @plays = 0 end def play @plays += 1 @@plays += 1 "This song: #@plays plays. Total #@@plays plays." end end s1 = Song.new("Song1", "Artist1", 234) # test songs s2 = Song.new("Song2", "Artist2", 345) puts s1.play puts s2.play puts s1.play puts s1.play 

Is @@ politely accessible only inside the Song class? This comment states that class variables are not recommended. Is it b / c that they are often not required during normal use and create many debugging headaches when used?

+1
ruby class-variables
May 15 '12 at 5:09
source share
3 answers

The variable @@ will be a class variable. This is usually a bad practice. There is a lot of it in your code because @plays == @@ is playing (unless you set @@ elsewhere in your code (bad practice))

Actually now, when I look at this, they are actually not the same. @plays counts how many times a single song has been played, and @@ plays with a count of all the songs. However, its probably the wrong practice of using @@ is playing. Usually you have a parent class such as "Player" that manages all the songs. The Player class must have an instance variable called @total_plays.

-3
May 15 '12 at 5:39
source share

Class variables are never required. But the reason is not that they are separated. I mean, it's good to avoid a shared state where you can, but this is not a real problem.

The reason they are recommended is, as shown in this article, they are really confusing . In particular, class variables of a class are separated by its subclasses and instances of its subclasses. For example:

 class Parent end class Child1 < Parent @@class_var = "Child1's" end class Child2 < Parent @@class_var = "Child2's" end 

With this code, Child1 and its instances will see a class variable named @@class_var with the value "Child1's" and Child2, and all its instances will see the class variable named @@class_var with the value "Child2's" . But suppose we later open Parent again and write the following:

 class Parent @@class_var = "Parent's" end 

Now, Parent and the instances it creates will see a class variable named @@class_var with the value "Parent's" . But that is not all . Now that the parent class has this variable, Child1 and Child2 suddenly share this variable, so all @@class_var have the value "Parent's" . And if you reassign the variable to Child1, it still shares, so all classes are updated. How confusing!

Instead of class variables, you can simply use class instance variables, for example:

 class Parent @class_var = "Parent's" def self.class_var @class_var end end class Child1 < Parent @class_var = "Child1's" end class Child2 < Parent @class_var = "Child2's" end 

Now Parent.class_var will return “Parent's”, Child1.class_var will return “Child1's” and Child2.class_var will return “Child2's” - exactly as you expect.

+17
May 16 '12 at 8:02
source share

A class variable is a variable that is shared among all instances of the class. This means that for all objects created from this class, there is only one variable value. This means that if one instance of an object changes the value of a variable, this new value will change significantly for all other instances of the object. Another way of thinking about class variables is with global variables in the context of one class.

 @@plays #is a class variable @plays #is an instance variable $plays #is a global variable accessed outside a class 

So, in your example, you created a class variable @@ to calculate the total number of songs played for all songs. Since this is a class variable, it cannot be accessed only outside the class. If you want to access the total number of plays, you can use a global variable. They start with the dollar sign $ play (in your case). I warn you, you should avoid using global variables since they are problematic for many reasons. One thing you can consider is to create a method that pops all the song instances into an array. Then you can summarize all the plays for all the songs through iterators. The path is more secure, less prone to programmer errors.

Edit: This is why global variables are bad

Are global variables bad?

+1
May 15 '12 at 5:52
source share



All Articles