7

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

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

但是我似乎无法证明类实例变量是合理的。

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

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

4

3 回答 3

4

假设您要计算类的实例数(不包括子类)

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

您不能使用 class 变量,因为它在所有类及其子类之间共享。@@count 请注意对byB和所做的更改如何C反映在 中A,但@count不共享。

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

于 2009-05-21T01:32:11.037 回答
3

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

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

于 2009-05-20T23:58:26.623 回答
3

是的,其实我有。这只是从我所拥有的内容中略微修改和修剪:

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"

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

有多种选择,语法很尴尬。鉴于我猜测使用它最自然的情况可能相当罕见。

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

CJ

于 2009-05-21T17:30:00.660 回答