Ruby procs和在没有实例化的情况下调用方法



我正试图让下面粘贴的这个RSpec测试通过,但我不知道应该如何调用multiply_by。我认为我必须将multiply_by存储为proc,以便在expect行上调用它,但是如果我不实例化NumProcessor类,我如何访问multiply_by方法?也许我不应该让NumProcessor成为一个类,但我需要使用.运算符,这样我才能做NumProcessor.multiply_by,所以我不清楚这一点。关于procs在ruby中的工作方式,我相信我有一些遗漏。任何指导都将不胜感激。

# First attempt 
class NumProcessor
def multiply_by(num)
multiply_by = Proc.new { |num| num * 2} 
end
end
# Trying to write code to make this test pass without changing it
describe 'NumProcessor#multiply_by' do
it 'should double' do
double = NumProcessor.multiply_by(2)
expect(double.call(4)).to eq(8)
end
end

更新的测试

class NumProcessor
def self.multiply_by(factor)
Proc.new { |num| num * factor} 
end
end
# Trying to write code to make this test pass without changing it
describe 'NumProcessor#multiply_by' do
it 'should double' do
double = NumProcessor.multiply_by(2)
expect(double.call(2)).to eq(4)
end
it 'should triple' do
triple = NumProcessor.multiply_by(3)
expect(triple.call(2)).to eq(6)
end
end

让他们工作起来!

我需要使用.运算符才能执行NumProcessor.multiply_by

为了在类本身上调用方法,您必须定义一个所谓的类方法,例如在其前面加上self.:(请参阅方法-范围(

class NumProcessor
def self.multiply_by(number)
# ...
end
end

您现在可以通过以下方式进行调用:

NumProcessor.multiply_by(4)
#=> #<Proc:...>

如果您不打算创建NumProcessor的实例,可以将其作为一个模块:

module NumProcessor
def self.multiply_by(number)
# ...
end
end

最后还有module_function——它将一个公共实例方法(一个没有self.的实例方法(变成了类方法和私有实例方法:

module NumProcessor
def multiply_by(number)
# ...
end
module_function :multiply_by
end

这就是内置Math模块的实现方式。该方法可以称为类方法:

NumProcessor.multiply_by(4)
#=> #<Proc:...>

但是,您也可以将模块包含到另一个类中,以便在没有显式接收器的情况下调用其方法:

class Foo
include NumProcessor
def bar
multiply_by(4)
end
end

同时不暴露在外:

foo = Foo.new
foo.bar
#=> #<Proc:...>
foo.multiply_by(4)
# NoMethodError: private method `multiply_by' called

关于您的实施:

  • multiply_by =赋值是多余的,因为multiply_by变量之后不会使用
  • 未使用number参数
  • 不管名称如何,multiply_by(number)总是乘以2(而不是乘以number(

要修复它,我会将其实现为:(请参阅Proc的文档,该文档使用了与示例完全相同的实现(

def multiply_by(factor)
Proc.new { |n| n * factor }
end

相应的测试可能如下所示:

describe 'NumProcessor' do
describe '.multiply_by' do
let(:multplier) { NumProcessor.multiply_by(factor) }
context 'with a factor of 2' do
let(:factor) { 2 }
it 'should double' do
expect(multiplier.call(4)).to eq(8)
end
end
context 'with a factor of 3' do
let(:factor) { 3 }
it 'should triple' do
expect(multiplier.call(4)).to eq(12)
end
end
end
end

通过在方法名称的开头添加self.,将multiply_by更改为类方法。

class NumProcessor
def self.multiply_by(number)
multiply_by = Proc.new { |num| num * 2} 
end
end

这将允许类似NumProcessor.multiply_by(4)的呼叫

最新更新