定义一个作用于数组的函数

时间:2014-05-27 17:37:21

标签: ruby

在Ruby中,我们定义类成员函数,如

class Dog
  def bark
    puts "woof"
  end
end

我想知道并且在google搜索中彻底失败的是,在Ruby中如何以及在何处定义处理对象数组的方法?

我希望能够做到这样的事情:

dogs = [Dog.new, Dog.new, Dog.new]
dogs.some_function

我如何以及在何处定义some_function

注意:我不是在解决特定问题之后,更多的是如何定义这样一个函数的步骤。

3 个答案:

答案 0 :(得分:5)

为了让你的所有狗都吠叫,你应该在阵列上使用each

dogs.each(&:bark)

相当于

dogs.each { |dog| dog.bark }

很少需要在数组上定义方法,在这种情况下,它将在所有数组上都可用,包含任何内容。要做到这一点,你需要在<{1}}类中声明它,再次声明它:

Array

然后你可以跑:

class Array
  def some_function
    # do something...
  end
end

以及

dogs = [Dog.new, Dog.new, Dog.new]
dogs.some_function

答案 1 :(得分:1)

您还可以创建一个继承自Array的类,例如

class DogWalker < Array
  def some_function
    self.each(&:bark)
  end
end

class Dog
  def bark
    puts "woof"
  end
end

d = DogWalker.new([Dog.new,Dog.new,Dog.new])
d.some_function 
#woof
#woof
#woof 
#=> [#<Dog:0x2a5a2e8>, #<Dog:0x2a5a2d0>, #<Dog:0x2a5a2b8>]

这意味着您只能在DogWalker的实例(以及Array可用的所有方法)上调用此方法,但不会更改Array本身。让您更好地控制其中包含的对象。 e.g。

class DogWalker < Array
  def initialize(args)
    raise ArgumentError.new("Must be an Array of Dogs") unless args.is_a?(Array) && args.all?{|e| e.is_a?(Dog)}
    super
  end
end

d = DogWalker.new([Dog.new,Dog.new,Dog.new])
#=>[#<Dog:0x2a5a2e8>, #<Dog:0x2a5a2d0>, #<Dog:0x2a5a2b8>]
d = DogWaler.new([Dog.new,12])
#=>ArgumentError: Must be an Array of Dogs
Array.new([1,2,3])
#=>[1,2,3]

正如@UriAgassi指出的那样,您很少需要更改基类,尤其是在设计不需要/不能跨对象类型应用的扩展功能时。这是一个例子:

class Array
  def some_function
    self.map(&:bark)
  end
end
class Dog
  def bark
    "woof"
  end
end
d = [Dog.new,Dog.new]
d.some_function
#=> ["woof","woof"]
d = [1,2,3,4]
d.some_function
#=>NoMethodError: undefined method `bark' for 1:Fixnum

由于Array可以接受任何对象类型,Array很好,但some_function方法需要一个responds_to bark的对象,该对象将在事件中引发对象无法执行请求的任务。

答案 2 :(得分:0)

在您的示例中,“狗”是Array class的实例。 如果要扩展Array类,可以像这样添加方法:

class Array
  def some_function
  end
end