2

我正在寻找一些方法链接。我有以下代码:

class MyClass

  attr_accessor :handler

  def do_a
    puts 'i just did a'
    self.handler = 'a'
    self
  end

  def do_b_if_a
    puts 'i just did b' if handler == 'a'
  end

 end

所以以下工作:

irb > test = MyClass.new
=> #<MyClass:0x007fa44ced9a70 @handler=nil>
irb > test.do_a
'i just did a'
irb > test.do_a.do_b_if_a
'i just did a'
'i just did b'

我不想工作的是当我第一次调用 do_a 它设置处理程序时,这意味着现在可以随时调用 do_b_if_a。但我只希望它在与 do_a 链接时被调用,我该怎么做?

4

4 回答 4

1

通常,您不想关心(在大多数情况下,您甚至不知道)是否以某种方式调用了您的方法。那就是疯狂。魔术调用序列使调试和测试时间变得非常糟糕。

但是,您可以做什么......而不是do_areturn self,在它周围包裹一个定义do_b的装饰器,然后返回装饰器。那时,您的原件MyClass不能do_b,因为它不知道如何操作。但是从do_a罐头里回来的东西。

(现在,您仍然可以说 likea = test.do_a和 then a.do_b,但如果不自己解析 Ruby 代码,您将无法真正解决这个问题。)

于 2012-04-03T22:17:20.747 回答
0

正如 cHao 所说,您不应该尝试方法调用模式。但我也可以想到另一种方法来做到这一点:

def do_a
  puts "i just did a"
  do_b_if_a(true)
end

def do_b_if_a(did_a=false)
  puts "i just did b" if did_a
end

do_a       # prints "i just did a"
do_b_if_a  # does nothing

当然,你可以打电话do_b_if_a(true),但它只会让它更灵活;)

于 2012-04-03T22:27:21.677 回答
0

我认为您在错误的地方跟踪状态。最好使用类似于 ActiveRecord 的查询接口的东西,例如:

class MyClass
  attr_accessor :handler

  def do_a
    puts 'i just did a'
    with_handler 'a'
  end

  def do_b_if_a
    puts 'i just did b' if handler == 'a'
  end

private

  def with_handler(h)
    o = dup
    o.handler = h
    o
  end

end

这样你总是有一个 MyClass 的实例,但你有一个一次性的副本来跟踪它的历史。这类似于cHao 的方法,但它不需要额外的装饰器类,因为 MyClass 可以装饰自己。

于 2012-04-03T22:45:46.177 回答
0

不会让你一直到那里,但你可以定义为在被调用do_b_if_a时添加的单例方法:to_a

class MyClass

  def do_a
    puts 'i just did a'
    self.tap{|s| def s.do_b_if_a; puts 'i just did b' end}
  end

 end

如果您想根据调用堆栈采取某些操作,您可以查看Kernel.caller 。但是,如果您没有充分的理由这样做,您可能会被其他开发人员打脸,哈哈。

于 2012-04-04T02:39:32.180 回答