Ruby中的类变量

sta*_*tor 1 ruby class-variables

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

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 
Run Code Online (Sandbox Code Playgroud)

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

Chu*_*uck 18

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

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

class Parent
end

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

class Child2 < Parent
  @@class_var = "Child2's"
end
Run Code Online (Sandbox Code Playgroud)

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

class Parent
  @@class_var = "Parent's"
end
Run Code Online (Sandbox Code Playgroud)

现在,Parent和它创建的实例都将看到一个@@class_var以该值命名的类变量"Parent's".但那还不是全部.既然父类有这个变量,Child1和Child2突然共享变量,所以所有@@class_vars都有值"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
Run Code Online (Sandbox Code Playgroud)

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