Ruby类对象扩展

Ruby类对象扩展,ruby,metaprogramming,Ruby,Metaprogramming,我是Ruby新手,一直在努力学习元编程。我想定义一个类并计算创建的对象数量,然后在调用ClassName.count时将其打印出来。(这将给出已创建对象的数量)。 这就是我到目前为止所做的: class Test @@number = 0 def initialize @@number += 1 end def self.Count puts "number is #{@@number}" end end Test.Count() # => 0

我是Ruby新手,一直在努力学习元编程。我想定义一个类并计算创建的对象数量,然后在调用
ClassName.count
时将其打印出来。(这将给出已创建对象的数量)。 这就是我到目前为止所做的:

class Test
  @@number = 0

  def initialize
    @@number += 1
  end

  def self.Count
    puts "number is #{@@number}"
  end 
end 

Test.Count() # => 0

test1 = Test.new
test2 = Test.new
Test.Count() # => 2

test3 = Test.new
Test.Count() # => 3

这可以工作并打印正确数量的已创建对象。但是,我应该使用类对象扩展来执行此操作,即不使用self方法(
self.foo
)或类属性(
@@number
)。这就是我被卡住的地方。我不确定我的解决方案和我需要实现的解决方案之间有什么区别。此外,任何关于本主题的阅读建议都是非常受欢迎的。

确实,您确实不应该使用“类变量”(例如
@@foo
);他们不是大多数人认为的那样,他们的行为举止令人惊讶/愚蠢。在大多数情况下,当您认为需要一个“类变量”时,实际上您只需要类本身上的一个实例变量(作为对象,它是类
的实例本身)


我不知道为什么不允许您定义单例方法(即“self-methods”),但这里有另一种方法,使用
类这样做是否符合您的要求

class Test
  @count = 0
  def initialize
    Test.instance_variable_set(:@count, Test.instance_variable_get(:@count)+1)
  end
  def count
    Test.instance_variable_get(:@count)
  end
end

Test.instance_variable_get(:@count)
  #=> 0
test1 = Test.new
test1.count
  #=> 1
test2 = Test.new
test2.count
  #=> 2
test1.count
  #=> 2
Test.instance_variable_get(:@count)
  #=> 2

你所说的令人惊讶或愚蠢的方式是什么意思?我知道这里可以使用类的实例变量,但在这种情况下,类变量是否有必要/更有用?@akallel这个问题有一个令人惊讶的类变量行为的好例子:。它们表现出意外的继承行为,并且相关的类会在您不期望的情况下覆盖变量。Ruby中的类变量确实没有好的用例可以用另一种方法更好地解决。我希望能够从测试类(
Test.count
)而不是从它创建的对象(即test1、test2等等)调用count。为什么编译器在这里考虑测试类的未定义计数?这就是我需要单例方法(self)的地方吗?Ruby会抱怨没有类方法
count()
,而不是没有类实例变量
@count
。要让
Test.count
返回
@count
的值,您需要按照@Jesse的建议,直接(
def self.count…
)或使用
attr\u reader
attr\u accessor
创建一个类方法
count()
。但是这些(以及拥有一个类实例变量)是否违反了您的禁令?您确定您正确地解释了“使用类对象扩展”吗?
class Test
  @count = 0
  def initialize
    Test.instance_variable_set(:@count, Test.instance_variable_get(:@count)+1)
  end
  def count
    Test.instance_variable_get(:@count)
  end
end

Test.instance_variable_get(:@count)
  #=> 0
test1 = Test.new
test1.count
  #=> 1
test2 = Test.new
test2.count
  #=> 2
test1.count
  #=> 2
Test.instance_variable_get(:@count)
  #=> 2