您是不是曾经在任何 Ruby 代码中使用过“类实例变量”?

Posted

技术标签:

【中文标题】您是不是曾经在任何 Ruby 代码中使用过“类实例变量”?【英文标题】:Have you ever used a "class instance variable" in any of your Ruby code?您是否曾经在任何 Ruby 代码中使用过“类实例变量”? 【发布时间】:2010-10-27 19:17:19 【问题描述】:

我可以理解为什么您需要一个类变量来跟踪诸如在该类中实例化的对象总数之类的事情。

我可以理解为什么您需要一个实例变量来存储该类中特定对象的属性。

但是类实例变量我似乎无法证明这一点。

据我了解,它们就像类变量一样,只是它们不像类变量那样对子类可见

这似乎是非常有限的用途。还是我错了?有没有人在他们的代码中找到了类实例变量的好用处?或者您能否举例说明这种细微差别很有价值的情况?

【问题讨论】:

【参考方案1】:

是的,实际上我有。这只是稍微修改和修剪了我所拥有的:

class Widget
  # class instance variable pattern
  class << self; attr_accessor :color; end

  def show_color()
    "This widget is #self.class.color"
  end
end
class WidgetR < Widget
  @color = "Russet"
end
class WidgetC < Widget
  @color = "Cordovan"
end
class WidgetL < Widget
  @color = "Liver"
end

WidgetR.new.show_color #=> "This widget is Russet"

但我不确定在我使用它的情况下是否真的有必要。我本可以覆盖该方法。或者提供了一种颜色方法。或者将其作为哈希存储在类变量中。或者甚至在每个实例中都保留一份副本(好吧,那个有点像)。我敢肯定还有其他可能...

有多种替代方案,语法笨拙。鉴于我猜测最自然使用它的情况可能相当罕见。

它可能会帮助您尝试使用类和实例变量来重现这种行为,并发现它很难实现(尽管如果您定义方法等很容易实现)。

C.J.

【讨论】:

【参考方案2】:

假设你要统计一个类的实例个数(不包括子类)

class A
  @count = 0
  @@count = 0
  def self.inherited(subclass)
    subclass.instance_eval  @count = 0 
  end
  def self.num_instances
    @count
  end
  def self.num_subclass_instances
    @@count
  end
  def self.new
    @count += 1
    @@count += 1
    super
  end
end
class B < A
end
class C < B
end

A.new
B.new
A.new
B.new
B.new
C.new

A.num_instances #=> 2
A.num_subclass_instances #=> 6
B.num_instances #=> 3
B.num_subclass_instances #=> 6
C.num_instances #=> 1
C.num_subclass_instances #=> 6

你不能使用类变量,因为它是共享的 类及其子类。请注意对@@count 所做的更改 BC 反映在 A 中,但 @count 不共享。

不过,一般来说,它对于存储任何特定于类的设置非常有用。 _why 在Dwemthy's Array 中使用它来指定实例属性的初始值,并且在进行 ruby​​ 元编程时经常出现。

【讨论】:

谢谢。很好的例子。因此,基本上,如果我们只有类变量,我们将无法为 A、B 和 C 做这些本地化计数之类的事情——我们将被困在相当于您的 num_subclass_instances 的情况下。我想我现在明白了。我不明白的唯一部分代码是: def self.inherited(subclass) subclass.instance_eval @count = 0 end。那有什么作用? 所以我在 A 的定义中初始化了 A 的 @count,但是我还需要将 A 的所有子类的 @count 初始化为 0,这就是代码所做的。当 A 被 subclass 继承时,我们打开子类并将其 @count 初始化为 0。尝试删除它,当 B 和 C 被实例化时你会看到 NoMethodErrors,因为 Ruby 不知道如何将 1 加到 nil (未实例化时@count 的默认值) 知道了。谢谢。顺便说一句,我正在寻找有关 instance_eval 的文档,并找到了 1.87 (rubybrain.com/api/ruby-1.8.7/doc/…) 但它看起来已经从 1.90 (rubybrain.com/api/ruby-1.9.0.2/doc/…) 消失了。 我不知道。我想在那种情况下你可以使用 subclass.instance_variable_set('@count',0) ruby-doc.org/core-1.9/classes/Object.html#M000306【参考方案3】:

类变量在类的所有实例之间共享,包括所有子类。有时这个跨层次结构的变量正是需要的,但有时您可能更喜欢为每个类使用不同的变量。与类变量不同,类实例变量会为每个类对象取不同的值。

http://martinfowler.com/bliki/ClassInstanceVariable.html

【讨论】:

以上是关于您是不是曾经在任何 Ruby 代码中使用过“类实例变量”?的主要内容,如果未能解决你的问题,请参考以下文章

谈谈Ruby中的类变量

c_cpp 曾经梦想过将“userInfo”添加到UIAlertView中吗?现在你可以!此类别允许您将任何对象分配给iOS 3.1中的任何对象

Mockito 对象不是声明类的实例

如何使用 Ruby 将文本输出着色到终端? [关闭]

Ruby类实例变量和继承

您是不是曾经使用欧盟或英国帐户从韩国登录 Bigquery?