如何在Ruby中正确链接自定义方法?

vis*_*Bar 10 ruby methods ruby-on-rails method-chaining

我正在尝试为以下两种方法执行链接方法.运行此代码后,我不断获得以下输出:

#<SimpleMath:0x007fc85898ab70>% 
Run Code Online (Sandbox Code Playgroud)

我的问题是:链接方法的正确方法是Ruby什么?

这是我的代码:

class SimpleMath


    def add(a,b=0)
        a + b
        return self
    end


    def subtract(a,b=0)
         a - b
        return self
    end

end
newNumber = SimpleMath.new()
print newNumber.add(2,3).add(2)
Run Code Online (Sandbox Code Playgroud)

Rus*_*nov 12

你想做这样的事吗?

class SimpleMath
  def initialize
    @result = 0
  end

  #1 add function
  def add(val)
    @result += val
    self
  end

  #2 Subtract function
  def subtract(val)
    @result -= val
    self
  end

  def to_s
    @result
  end
end

newNumber = SimpleMath.new
p newNumber.add(2).add(2).subtract(1)
Run Code Online (Sandbox Code Playgroud)

对于任何数量的论点

class SimpleMath
  def initialize
    @result = 0
  end

  #1 add function
  def add(*val)
    @result += val.inject(&:+)
    self
  end

  #2 Subtract function
  def subtract(*val)
    @result -= val.inject(&:+)
    self
  end

  def to_s
    @result
  end
end

newNumber = SimpleMath.new
p newNumber.add(1, 1).add(1, 1, 1, 1).subtract(1)
Run Code Online (Sandbox Code Playgroud)


Car*_*and 6

让我们定义一个类的实例SimpleMath:

sm = SimpleMath.new #=> #<SimpleMath:0x000001020ca820>
Run Code Online (Sandbox Code Playgroud)

这里要注意三件事:

  • sm是一个变量.在Ruby中,变量由小写字母表示,可选地用下划线分隔(例如my_var).
  • 而它的确定添加()new,在new没有参数(又名"参数"),这是可选的,很少有人会这么做.
  • 如果关键字return不存在,Ruby返回该方法执行的最后一次计算.在这里,您通常会简单地写下最后一行self,然后返回.唉,重要的是self,无论有或没有关键字return,返回都不是你想要的.

在IRB中尝试以下内容:

sm.add(2) #=> #<SimpleMath:0x000001020ca820>
Run Code Online (Sandbox Code Playgroud)

毫无疑问,你会期待它返回2+0 #=> 2,但它会返回self,正如你在上面看到的那样,实际上是sm(#<SimpleMath:0x000001020ca820>).

您只需删除该行即可解决此问题:

return self
Run Code Online (Sandbox Code Playgroud)

来自addsubtract:

class SimpleMath
  def add(a,b=0)
    a + b
  end

  def subtract(a,b=0)
    a - b
  end
end
Run Code Online (Sandbox Code Playgroud)

现在

sm = SimpleMath.new
sm.add(2) #=> 2
Run Code Online (Sandbox Code Playgroud)

但是,如果我们试图链接另一个add,我们还有另一个问题:

sm.add(2).add(2,3) #=> NoMethodError: undefined method `add' for 2:Fixnum
Run Code Online (Sandbox Code Playgroud)

这个消息是很清楚的:类Fixnum,其中的2是一个实例,没有命名的实例方法add.那是因为你为班级定义了它SimpleMath,而不是为了Fixnum.

当Ruby执行时sm.add(2).add(3,4),它首先计算sm.add(2) #=> 2,这会将表达式减少到2.add(3,4).然后它尝试发送方法add(带有两个参数)2,但发现该类2.class #=> Fixnum没有实例方法add; 因此例外.

我们可以通过为类定义这些方法来纠正该错误Fixnum:

class Fixnum
  def add(a,b=0)
    a + b
  end

  def subtract(a,b=0)
    a - b
  end
end
Run Code Online (Sandbox Code Playgroud)

您可以Fixnum通过运行以下命令确认已将这些方法添加到类中:

Fixnum.instance_methods.sort
Run Code Online (Sandbox Code Playgroud)

现在,另一个问题:

sm = Fixnum.new #=> NoMethodError: undefined method `new' for Fixnum:Class
Run Code Online (Sandbox Code Playgroud)

哦,我的,班级Fixnumnew办法!那是因为实例Fixnum是整数,无法创建.您可以轻松确认整数是以下情况的实例Fixnum:

72.class #=> Fixnum
-3.class #=> Fixnum
Run Code Online (Sandbox Code Playgroud)

所以我们可以add通过将它发送到任何 Fixnum实例来调用该方法:

72.add(2) #=> 2
-3.add(2) #=> 2
Run Code Online (Sandbox Code Playgroud)

现在让我们尝试连锁add操作:

72.add(2).add(3,4)       #=> 7
72.add(2000000).add(3,4) #=> 7
Run Code Online (Sandbox Code Playgroud)

没有例外,但没有链接.解决此问题的方法是再次更改方法:

class Fixnum
  def add(b=0)
    puts "in add, self = #{self}, b = #{b}"
    self + b
  end

  def subtract(b=0)
    puts "in subtract, self = #{self}, b = #{b}"
    self - b
  end
end
Run Code Online (Sandbox Code Playgroud)

我已经puts在每个方法中添加了一个语句,以防需要更多调试.当代码正常工作时,我们将删除它们.我们来测试一下:

2.add(3)                    #=> 5
  in add, self = 2, b = 3
5.add                       #=> 5
  in add, self = 5, b = 0
5.add(7)                    #=> 12
  in add, self = 5, b = 7
2.add(3).add.add(7)         #=> 12
  in add, self = 2, b = 3
  in add, self = 5, b = 0
  in add, self = 5, b = 7

2.subtract(5)               #=> -3
  in subtract, self = 2, b = 5
-3.subtract                 #=> -3
  in subtract, self = -3, b = 0
2.subtract(5).subtract      #=> -3
  in subtract, self = 2, b = 5
  in subtract, self = -3, b = 0

2.add(3).subtract(5).add(7) #=>  7
  in add, self = 2, b = 3
  in subtract, self = 5, b = 5
  in add, self = 0, b = 7
Run Code Online (Sandbox Code Playgroud)

成功!得到它?