我希望做一些方法链接。我有以下代码:
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链接时调用它,我该怎么做?
答案 0 :(得分:1)
一般情况下,如果以某种方式调用方法,您不想关心(在大多数情况下,您甚至不会知道)。那种方式就是疯狂。魔术呼叫序列可以进行调试和测试。
你可以做什么,但是......而不是让do_a
返回self
,在它周围包装一个定义do_b
的装饰器,然后返回装饰器。此时,您的原始MyClass
无法do_b
,因为它不知道如何。但是从do_a
返回的东西可以。
(现在,您仍然可以说a = test.do_a
然后a.do_b
,但如果不自行解析Ruby代码,就无法解决这个问题。)
答案 1 :(得分: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)
,但之后它会让它更灵活;)
答案 2 :(得分: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's方法类似,但它不需要额外的装饰器类,因为MyClass可以自己修饰。
答案 3 :(得分: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。但是,如果你没有充分的理由,你可能会被另一位开发人员搞砸了,哈哈。