简体   繁体   English

Ruby:对委托方法执行其他命令

[英]Ruby: Performing additional commands on delegated method

I'd like to use delegate to pass map from a string on to chars, then join back to a string result. 我想使用委托将映射从字符串传递到chars,然后再联接回字符串结果。

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

As it's originally a string I'd like to perform join after the delegated method has performed its duties. 由于这是原来的字符串我想执行委托的方法已履行职责后加入 How do I modify the delegate line to include the additional change? 如何修改委托行以包括其他更改? The closest thing I've seen online is SimpleDelegator with __setobj__ . 我在网上看到的最接近的东西是带有__setobj__ SimpleDelegator But that's not well documented and I'm not able to ascertain how to use it for this. 但这还没有很好的记录,因此我无法确定如何使用它。

I'm strictly looking for an answer in regards to delegate or SimpleDelegate 我严格在寻找有关委托或SimpleDelegate的答案

The equivalent behavior I'm looking for is this: 我正在寻找的等效行为是这样的:

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

I'm looking to understand how to do this with delegate. 我想了解如何使用委托进行此操作。

The Fowardable docs are hilarious--as if that first example will run without a hundred errors. Fowardable文档非常有趣-好像第一个示例将运行而没有一百个错误。 Your pseudo code tells ruby to forward the method call String#map , which doesn't exist, to String#chars , and you want to join() the result of that? 您的伪代码告诉ruby将不存在的方法调用String#map转发到String#chars ,您是否想要join()结果? Skip all the method calls and just write puts "some_string" . 跳过所有方法调用,只写puts "some_string" So your question doesn't seem to make a lot of sense. 因此,您的问题似乎没有多大意义。 In any case, Forwardable#delegate() does not allow you to map one name to another name. 无论如何, Forwardable#delegate()不允许您将一个名称映射到另一个名称。

With regards to SimpleDelegat**or**, you can do this: 关于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

Response to edit: The equivalent behavior I'm looking for.. 编辑回应: 我正在寻找的等效行为。

The problem is ruby won't let you do this: 问题是红宝石不允许您这样做:

class String < SomeClass
end

which is what include does, and you need to be able to do that in order to use delegate to forward all the method calls sent to one class to another class. 这就是include所做的事情,您需要能够做到这一点,才能使用委托将发送到一个类的所有方法调用转发到另一类。 This is the best you can do: 这是您可以做的最好的事情:

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

Or: 要么:

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

Of course, you could always override String#method_missing() to do what you want. 当然,您始终可以重写String#method_missing()来执行所需的操作。 What is it that you read about delegate that made you think it could replace include? 您读到的有关委托的什么使您认为它可以代替include?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM