Ruby:在委派方法上执行其他命令

时间:2014-09-20 18:32:23

标签: ruby delegates

我想使用委托将字符串从字符串传递到字符,然后再连接回字符串结果。

require 'forwardable'

module Map
  module String
    extend Forwardable

    def self.included(base)
      base.send :extend, Forwardable
    end

    # Map for String
    delegate map: :chars
  end
end

class String
  include Map::String
end

因为它原本是一个字符串,所以我希望在委托方法执行其职责后执行 join 。如何修改委托行以包含其他更改?我在网上看到的最接近的是SimpleDelegator __setobj__。但是没有详细记录,我无法确定如何使用它。

我正在寻找关于委托或SimpleDelegate的答案

我正在寻找的等效行为是:

module Map
  module String

    def map(*args, &block)
      if (!args.compact.empty? || !block.nil?)
        self.chars.map(*args,&block).join
      else
        self.chars.map(*args,&block)
      end
    end
  end
end

class String
  include Map::String
end

我希望了解如何使用委托来完成此任务。

1 个答案:

答案 0 :(得分:1)

Fowardable文档非常有趣 - 好像第一个例子将在没有一百个错误的情况下运行。您的伪代码告诉ruby将方法调用String#map(不存在)转发给String#chars,并且您想要加入()结果吗?跳过所有方法调用,然后只写puts "some_string"。所以你的问题似乎没有多大意义。在任何情况下,Forwardable#delegate()都不允许您将一个名称映射到另一个名称。

关于SimpleDelegat **或**,你可以这样做:

module Map
  require 'delegate'

  class MyStringDecorator < SimpleDelegator
    def map
      chars.shuffle.join('|')
    end
  end
end


d = Map::MyStringDecorator.new 'hello'
puts d.map

--output:--
h|o|l|l|e

对编辑的回应:我正在寻找的等效行为..

问题是ruby不会让你这样做:

class String < SomeClass
end

这是include的作用,你需要能够这样做才能使用委托将发送到一个类的所有方法调用转发给另一个类。这是你能做的最好的事情:

require 'delegate'

class MyString < DelegateClass(String)
  def map(*args, &block)
    if (!args.compact.empty? || !block.nil?)
      self.chars.map(*args,&block).join
    else
      self.chars.map(*args,&block)
    end
  end
end

s = MyString.new 'hello'
puts s.upcase
puts s.map {|letter| letter.succ }

--output:--
HELLO
ifmmp

或者:

require 'forwardable'

class MyString
  extend Forwardable

  def initialize(str)
    @str = str
  end

  def_delegators :@str, :upcase, :capitalize, :[], :chars  #etc., etc., etc.
  #Or: delegate({[:upcase, :capitalize, :[], :chars] => :@str})
  #Or: instance_delegate({[:upcase, :capitalize, :[], :chars] => :@str})


  def map(*args, &block)
    if (!args.compact.empty? || !block.nil?)
      self.chars.map(*args,&block).join
    else
      self.chars.map(*args,&block)
    end
  end
end

s = MyString.new('hello')
puts s.upcase
puts s.map {|letter| letter.succ }

--output:--
HELLO
ifmmp

当然,你总是可以覆盖String#method_missing()来做你想做的事。你读到的关于委托的内容是什么让你觉得它可以取代包括?