Ruby中的类变量

我在本教程中遇到了以下示例:

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 

@@只能在课堂上礼貌地播放吗? 这篇评论提出了不建议使用类变量的观点。 是不是通常在日常使用中不需要它们,并且在使用时会产生很多调试问题?

@@变量将是一个类变量。 这通常是不好的做法。 在你的代码中它是多余的,因为@plays == @@ play(除非你在你的代码中将@@ play放在其他地方(不好的做法))

实际上现在我看它,它们并不是真的一样。 @plays会记录个别歌曲的播放次数,而@@ plays将统计所有歌曲。 尽管如此,使用@@ play可能也是不好的做法。 通常,你会有像“播放器”这样的父类管理所有歌曲。 在“Player”类中应该有一个名为@total_plays的实例变量。

从来没有真正需要类变量。 但原因并不是他们是共享国家。 我的意思是,尽可能避免共享状态是好的,但这不是真正的问题。

他们被推荐反对的原因是,正如那篇文章所示,他们真的很混乱 。 特别是,类的类变量由其子类和子类的实例共享。 例如:

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

使用此代码,Child1及其实例将全部看到名为@@class_var的类变量,其值为"Child2's" "Child1's"而Child2及其实例都将看到名为@@class_var的类变量,其值为"Child2's" 。 但是假设稍后我们重新打开Parent并写下这个:

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

现在Parent和它创建的实例都将看到一个名为@@class_var的类变量,其值为"Parent's"但这不是全部 。 既然父类有这个变量,Child1和Child2突然共享变量,所以所有的@@class_var都有值"Parent's" 。 如果你在Child1中重新分配变量,它仍然是共享的,所以所有类都会更新。 多么令人困惑!

您可以只使用类的实例变量而不是类变量,如下所示:

 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 

现在, Parent.class_var将返回“Parent's”, Child1.class_var将返回“ Child2.class_var 's”, Child2.class_var将返回“Child2's” - 就像您期望的那样。

类变量是在类的所有实例之间共享的变量。 这意味着对于从此类实例化的所有对象,只存在一个变量值。 这意味着如果一个对象实例更改了变量的值,则该新值将基本上针对所有其他对象实例进行更改。 思考类变量的另一种思考方式是在单个类的上下文中作为全局变量。

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

因此,在您的示例中,您创建了一个类变量@@ plays来计算为所有歌曲播放的歌曲总数。 由于它是一个类变量,因此不能仅在类外部访问它。 如果要访问总播放次数,可以使用全局变量。 他们以美元符号$ play开头(在你的情况下)。 我警告你,你应该远离使用全局变量,因为它们存在问题,原因有很多。 您可以考虑的一件事是创建一个将所有歌曲实例推送到数组中的方法。 然后,您可以通过迭代器对所有歌曲的所有播放进行求和。 方式更安全,更不容易出现程序员错误。

编辑:这就是全局变量不好的原因

全球变量是否糟糕?