如何计算类的实例而不计算重新分配?

时间:2013-12-29 01:12:52

标签: ruby class methods instances

我正在研究类方法。

我正在尝试计算一个类的创建实例的数量。我可以通过在initialize方法中创建一个计数器变量来实现这一目的。

当我重新分配最初分配给一个类实例的变量时,会出现问题。因为initialize方法被调用两次,所以它不会识别该变量只是被重新分配给另一个类实例。

class Ticket
    attr_accessor :price
    attr_reader :event, :venue

    @@count = 0
    @@tickets = {}

    def initialize(event, venue)
        @event = event
        @venue = venue

        @@count += 1
    end

    def self.count
        @@count 
    end
end

a = Ticket.new("Michael Buble", "Staples")

a = Ticket.new("Frank Sinatra", "Madison Square Garden")

puts "Ticket count of #{Ticket.count}"

当我在IRB中运行上面的代码时,它给了我一个Ticket count of 2(如预期的那样)。如何更改代码以便识别覆盖?

注意:我知道之前已经针对目标C提出了这个问题,但问题的重新分配方面为问题添加了不同的元素。别的我知道。

4 个答案:

答案 0 :(得分:3)

ObjectSpace.each_object(Ticket).count

将为您提供当前内存中对象的计数。在IRB中进行测试时,我发现它遇到了您描述的问题,即使您已为变量分配了新对象,对象也会在内存中保留。从技术上讲,即使您将新实例分配给变量“a”,该对象仍然存在。

请参阅此文章:Deleting an object in Ruby答案中有大量有关您要执行的操作的信息。

答案 1 :(得分:2)

在现实世界中,你不会计算内存中的实例,你会问一个数据库有多少存在。你需要从数据库的角度思考。

您使用a重复包含Ticket实例是错误的。您应该使用Array,Hash或Set来维护列表,然后询问容器存在多少:

require 'set'

class Ticket
  attr_accessor :price
  attr_reader :event, :venue

  @@tickets = Set.new

  def initialize(event, venue)
    @event = event
    @venue = venue

    @@tickets << self
  end

  def delete
    @@tickets.delete(self)
  end

  def self.count
    @@tickets.size
  end

end

a = Ticket.new("Michael Buble", "Staples")
b = Ticket.new("Frank Sinatra", "Madison Square Garden")

puts "Ticket count of #{Ticket::count}"
b.delete
puts "Ticket count of #{Ticket::count}"

你可以通过添加从@@tickets检索特定实例的方法来构建它,添加to_s以便列出它们,但是,最后,你会想要使用真实的数据库。如果您的代码因任何原因而崩溃,您的整个故障单将会消失,这在现实生活中是不可接受的。

答案 2 :(得分:0)

如果确实想要计算Ticket课程的实时实例(由于我无法理解的原因),@ Beechech有正确的想法:

class Ticket
  attr_reader :event, :venue

  def initialize(event, venue)
    @event = event
    @venue = venue
  end   

  def self.count_live_instances
    ObjectSpace.garbage_collect
    ObjectSpace.each_object(self).to_a.size
  end
end

a = Ticket.new("Michael Buble", "Staples")
b = Ticket.new("Cher", "Canadian Tire Center")
a = Ticket.new("Frank Sinatra", "Madison Square Garden")

puts "Ticket instances count = #{Ticket.count_live_instances}" # => 2

在调用ObjectSpace#each_object之前进行垃圾收集至关重要。如果您持怀疑态度,请插入p ObjectSpace.each_object(self).to_a.size作为self.count_live_instances的第一行。它将打印3

(还有一个方法ObjectSpace#count_objects。此方法返回类似这样的哈希值:{:TOTAL=>56139,..., :T_ARRAY=>3139,..., :T_ICLASS=>32}。不幸的是,键是“对象类型”;您将找不到:TICKET其中。)

答案 3 :(得分:0)

class Gs def self.method1 code... end def self.method2 code... end def self.method3 code... end end Gs.new p Gs.singleton_methods.count

Gs.singleton_methods.count将打印3 如果我们使用self关键字或 classname.method name ..