ruby - Ruby 中的类变量

标签 ruby class-variables

我从 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 

@@plays 是否只能在 Song 类中礼貌地访问? This commentary提出了不推荐使用类变量的观点。是不是因为它们在日常使用中通常不是必需的,并且在使用时会产生很多令人头疼的调试问题?

最佳答案

类变量从来都不是真正需要的。但原因并不是它们是共享状态。我的意思是,尽可能避免共享状态是件好事,但这不是这里的真正问题。

他们被反对的原因是,如那篇文章所示,他们真的很困惑。特别是,一个类的类变量由它的子类和它的子类的实例共享。例如:

class Parent
end

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

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

使用这段代码,Child1 及其实例都将看到名为 @@class_var 且值为 "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 将返回“Child1's”,Child2.class_var 将返回“Child2's”——正如您所期望的那样。

关于ruby - Ruby 中的类变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10594444/

相关文章:

ruby - RVM 安装的 mysql2 gem 可以很好地与 Rails 配合使用...但不能与独立的 Ruby 脚本配合使用

ruby-on-rails - 如何在模块外部调用方法

mysql - Ruby on Rails : MySQL client library issue when trying to create database

java - 如何在声明之前访问静态变量?

ruby - 为什么这不起作用 : x. map (&:+"A")

ruby-on-rails - 如何在异常发生后继续处理 Ruby 中的 block ?

Python:定义类变量时可以访问哪些范围?

ios - 在 Objective-C 中使用类似 C 的静态变量是不好的做法吗?

java - 如果声明但未初始化对象的变量是否会使用内存空间?

C++类变量声明和使用顺序?