Ruby:模块,Mixin和块令人困惑吗? [英] Ruby: Module, Mixins and Blocks confusing?

查看:77
本文介绍了Ruby:模块,Mixin和块令人困惑吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是我尝试从Ruby Programming书中运行的代码 http://www.ruby-doc.org/docs/ProgrammingRuby/html /tut_modules.html

为什么product方法没有提供正确的输出? 我用irb test.rb来运行它.我正在运行Ruby 1.9.3p194.

 module Inject
  def inject(n)
    each do |value|
      n = yield(n, value)
    end
    n
  end

  def sum(initial = 0)
    inject(initial) { |n, value| n + value }
  end

  def product(initial = 1)
    inject(initial) { |n, value| n * value }
  end
end

class Array
  include Inject
end

[1, 2, 3, 4, 5].sum            ## 15
[1, 2, 3, 4, 5].product        ## [[1], [2], [3], [4], [5]]
 

解决方案

顺便说一句:在Ruby 2.0中,有两个功能可以帮助您解决两个问题.

Module#prepend 在继承链中添加,以便将混入模块/类中的mixin override 方法中定义的方法混入其中. /p>

精炼允许按词法作用域进行猴子修补.

它们在起作用(您可以通过RVM或ruby-build轻松获得最新版本的YARV 2.0):

module Sum
  def sum(initial=0)
    inject(initial, :+)
  end
end

module ArrayWithSum
  refine Array do
    prepend Sum
  end
end

class Foo
  using ArrayWithSum

  p [1, 2, 3].sum
  # 6
end

p [1, 2, 3].sum
# NoMethodError: undefined method `sum' for [1, 2, 3]:Array

using ArrayWithSum
p [1, 2, 3].sum
# 6

Following is the code I tried to run from the Ruby Programming Book http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_modules.html

Why doesn't the product method give the right output? I ran it with irb test.rb. And I am running Ruby 1.9.3p194.

module Inject
  def inject(n)
    each do |value|
      n = yield(n, value)
    end
    n
  end

  def sum(initial = 0)
    inject(initial) { |n, value| n + value }
  end

  def product(initial = 1)
    inject(initial) { |n, value| n * value }
  end
end

class Array
  include Inject
end

[1, 2, 3, 4, 5].sum            ## 15
[1, 2, 3, 4, 5].product        ## [[1], [2], [3], [4], [5]]

解决方案

By the way: in Ruby 2.0, there are two features which help you with both your problems.

Module#prepend prepends a mixin to the inheritance chain, so that methods defined in the mixin override methods defined in the module/class it is being mixed into.

Refinements allow lexically scoped monkeypatching.

Here they are in action (you can get a current build of YARV 2.0 via RVM or ruby-build easily):

module Sum
  def sum(initial=0)
    inject(initial, :+)
  end
end

module ArrayWithSum
  refine Array do
    prepend Sum
  end
end

class Foo
  using ArrayWithSum

  p [1, 2, 3].sum
  # 6
end

p [1, 2, 3].sum
# NoMethodError: undefined method `sum' for [1, 2, 3]:Array

using ArrayWithSum
p [1, 2, 3].sum
# 6

这篇关于Ruby:模块,Mixin和块令人困惑吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆