返回ruby中类的所有对象的属性

时间:2013-12-19 18:09:43

标签: ruby

我对Ruby(以及一般的编程)很陌生,但我认为有一种方法可以调用所有类对象的属性吗?

    class Player
      attr_reader :number

      def initialize(name, number)
        @name = name
        @number = number
      end

      def self.all_numbers
        [] << Player.each {|person| person.number}
      end
    end

   guy1 = Player.new('Bill', 23)
   guy2 = Player.new('jeff', 18)

我想通过调用类来访问所有对象的数字..

   Player.all_numbers

希望回归..

    [23, 18]

4 个答案:

答案 0 :(得分:5)

您现在遇到的问题是Player是您的自定义类。它不响应类方法each。另一个问题是Player类不知道在它之外创建的实例。

有很多方法可以解决这个问题。我这样做的方法是实现另一个名为Team的类,如此

class Team
  def initialize(*players)
    @players = players
  end

  def player_numbers
    @players.map { |player| player.number }
  end
end

class Player
  attr_reader :number

  def initialize(name, number)
    @name = name
    @number = number
  end
end

guy1 = Player.new('Bill', 23)
guy2 = Player.new('jeff', 18)

team = Team.new(guy1, guy2)
team.player_numbers
#=> [23, 18]

答案 1 :(得分:2)

ObjectSpace#each_object的帮助下写下如下:

  

在此Ruby进程中为每个活动的非临时对象调用块一次。如果指定了module,则仅为那些匹配(或是其子类)模块的类或模块调用块。返回找到的对象数。永远不会返回立即对象(Fixnums,符号true,false和nil)。

     

如果没有给出阻止,则返回枚举器。

class Player
  attr_reader :number

  def initialize(name, number)
    @name = name
    @number = number
  end

  def self.all_numbers
    ObjectSpace.each_object(self).map(&:number)
  end
end

guy1 = Player.new('Bill', 23) 
guy2 = Player.new('jeff', 18) 


Player.all_numbers
# => [18, 23]

另一种方法

class Player
  attr_reader :number
  @class_obj = []

  def initialize(name, number)
    @name = name
    @number = number
    self.class.add_object(self)
  end

  def self.add_object(ob)
    @class_obj << ob
  end

  def self.all_numbers
    @class_obj.map(&:number)
  end
end

guy1 = Player.new('Bill', 23)  
guy2 = Player.new('jeff', 18)  

Player.all_numbers
# => [23, 18]

答案 2 :(得分:0)

使用类变量

从设计角度来看,使用Team来保存对完整Player对象的引用可能更合适,但您可以使用简单的类变量来执行所需的操作。例如:

class Player
  attr_reader :number

  @@numbers = []

  def initialize(name, number)
    @name = name
    @number = number
    @@numbers << @number
  end

  def self.all_numbers
    @@numbers
  end
end

guy1 = Player.new 'Bill', 23
guy2 = Player.new 'jeff', 18

Player.all_numbers 
#=> [23, 18]

对于这个简单的用例,这可能就足够了。但是,如果您发现自己试图将整个Player对象填充到Player类变量中,那么您肯定希望找到一个更好的名词(例如团队或玩家)来保存您的集合。

答案 3 :(得分:0)

我只是覆盖new并将实例保存在类变量中:

    class Player
      attr_reader :number

      def initialize(name, number)
        @name = name
        @number = number
      end

      def self.new(*args)
        (@@players ||= []) << super
        @@players.last
      end

      def self.all_numbers
        @@players.reduce([]) {|arr, player| arr << player.number}
      end
    end

   Player.new('Bill', 23)
   Player.new('jeff', 18)
   p Player.all_numbers # => [23, 18]

Carpk,我应该解释一些事情:

  • 通常,Player.new('Bill', 23)会将方法Class#new与两个参数一起发送到类Player。通过在此定义self.new,我将覆盖Class#newself.new调用super,它使用Class#new的参数调用self.new(除非您只想传递一些参数,否则不需要显式传递参数)。 Class#new将新的类实例返回给self.new,它也会返回它,但首先会将其保存在数组@@player中。
  • (@@players ||= [])是典型的Ruby技巧。这具有将@@players设置为等于空数组(如果尚未定义)(为零)的效果,并且如果它已经是数组(空或不是)则保持不变。这是因为@@players ||= []@@players = @@players || []相同。如果@@players => nil,则变为@@players = [];否则,@@players保持不变(永远不会评估[])。可爱,嗯?
  • @@players.last返回Class#new刚刚返回的类实例,并添加到@@players的末尾。
  • @@players.reduce([]) {|arr, player| arr << player.number}创建并返回类实例的数组arr,然后self.all_numbers返回。 reduce的参数是累加器的初始值,这里是块中名为arr的空数组。注意reduceinject是同义词。

Carpk,不要再读了;这只会令人困惑。

我撒了谎。我实际上不会这样做。我建议使用类变量和类方法,因为Carpk是Ruby的新手,可能不会大量使用元编程。我实际上要做的是定义一个类实例变量@players并制作类new的{​​{1}}和all_numbers单例方法。这样,类Player的实例将无法轻松访问该变量或这两种方法。为此,只需使用以下内容替换Playerself.new的上述定义:

self.all_numbers

Carpk,我警告过你。