0

在开始RubyMonk 2 级时,我看到了这个:

class Calculator
  def add(a, b)
    return a + b
  end
end

addition_method = Calculator.new.method("add")
addition        = addition_method.to_proc

puts addition.call(5, 6)

我以前从未见过method,我查阅了文档

所以我现在的理解是:

如果你想从一个类中窃取一个方法,并把它变成一个proclambda?),你把它贴method在你想要的类方法的名字之前,然后用引号括起来或写成一个符号。

这是正确的思考方式吗?或者它至少是 的主要用途Object#method

4

2 回答 2

4

我认为你的想法是正确的。更一般地说,该method方法只是将 Ruby 方法表示为Method 对象的一种方式,并且由于对象很有用,这可能出于多种原因而有用。

该示例代码中有一些无关紧要的东西。这是另一个例子:

def add(a)
  a + a
end

m = method(:add)  # => #<Method: Object#add>
m.call(4)         # => 8

这是另一个有用的示例:

def good?(n)
  n > 5
end

[1, 4, 9].select(&method(:good?))   # => [9]
于 2013-10-24T20:48:43.393 回答
0

基本上是的。该方法使您可以将方法及其method接收器“打包”到 class 的单个对象中。接收器是您调用的对象。对象也称为“绑定”方法,因为它绑定(附加)到接收器。Method.methodMethod

例子:

class Car
  attr_accessor :make, :model

  def initialize(make, model)
    @make, @model = make, model
  end

  def drive(speed)
    puts "#{@make}-#{@model} drove with speed #{speed}"
  end
end

创建一个实例:

car1 = Car.new('Toyota', 'Corolla')

获取方法并调用它:

car1drive = car1.method(:drive)
# Outputs "Toyota-Corolla drove with speed 5"
car1drive.call(5)

请注意,我们无需将其转换为 aproc即可使用call

接收机绑定

为了演示该方法如何仍然绑定到它的接收器,我们修改了接收器。请注意Method仍然如何依赖于它来自的对象。即创建Method没有对接收者的状态进行快照,而是在每次调用它时咨询接收者。

car1.model = 'Rav4'
# Outputs "Toyota-Rav4 drove with speed 5"
car1drive.call(5)

我们还可以检索接收者:

car1drive.receiver == car1  # true

作为一个块使用

它可以通过 using &(隐式调用to_proc)来代替块。这很好用,因为each为块产生一个参数,并且我们的car1drive方法也接受一个参数。

# Outputs:
# Toyota-Rav4 drove with speed 1
# Toyota-Rav4 drove with speed 2
# Toyota-Rav4 drove with speed 3
[1,2,3].each(&car1drive)

未绑定的方法

我们还可以获取一个未绑定的方法并将其绑定到另一个Car.

unbind返回一个全新的UnboundMethod;它不会改变绑定方法。

# This gives us an UnboundMethod.
# It can't be called; it's like a disembodied spirit.
# This doesn't change car1drive at all.
unbound_drive = car1drive.unbind

car2 = Car.new('Chevy', 'Cruze')
car2drive = unbound_drive.bind(car2)
# Outputs "Chevy-Cruze drove with speed 5"
car2drive.call(5)

UnboundMethod直接使用类也可以得到与上面相同的Car效果:

unbound_drive = Car.instance_method(:drive)

调用已在子类中覆盖的超类方法

这是一个很好的技巧,你可以调用一个被覆盖的方法。假设您有一个覆盖方法的子类:

class Jalopy < Car
  def drive(speed)
    puts "The ailing #{@make}-#{@model} drove with speed #{speed}"
  end
end

jal1 = Jalopy.new('Toyota', 'Corolla')
# Outputs "The ailing Toyota-Corolla drove with speed 5"
jal1.drive(5)

# I don't like the overridden output, give me the original instead!
unbound_car_drive = Car.instance_method(:drive)
car_drive_on_jal1 = unbound_car_drive.bind(jal1)

# Outputs "Toyota-Corolla drove with speed 5"
car_drive_on_jal1.call(5)

我们只能这样做,因为jal1is a Car( jal1.is_a?(Car)is true)

我不建议在实际应用程序中使用上述方法,因为它使代码很难管理 - 但有时它有助于排除故障。

于 2013-10-24T21:45:28.367 回答