我正在做一些涉及Ruby中异步回调的编程,需要将回调方法传递给另一个对象(可能静态调用也可能不调用)。我遇到的问题是实例回调的语法 - 我知道它相当复杂,但我不确定我能否使它变得更简单。这就是我所拥有的:
class OBJA
def self.staticMethod(text, returnCall)
puts "objA.staticMethod: #{text}"
OBJB.send(returnCall, "Call back from objA.staticMethod")
end
def instanceMethod(text, returnCall)
puts "objA.instanceMethod: #{text}"
OBJB.send(returnCall, "Call back from objA.instanceMethod")
end
end
class OBJB
def starterMethod
OBJA.staticMethod("foo", :returnedCall)
OBJA.new.instanceMethod("bar", :returnedCall)
end
def returnedCall(text)
puts text
end
end
您可以通过执行以下操作来执行它:
b = OBJB.new
b.starterMethod
谢谢!
答案 0 :(得分:2)
我遇到的问题是实例回调的语法
您必须使用实例调用实例方法。如果你在类上调用类方法,例如OBJB.send(...)
,必须定义类方法。
class OBJA
def self.staticMethod(text, methName)
puts "objA.staticMethod: #{text}"
OBJB.send(methName, "Call back from objA.staticMethod")
end
def instanceMethod(text, methName)
puts "objA.instanceMethod: #{text}"
OBJB.new.send(methName, "Call back from objA.instanceMethod")
end
end
class OBJB
def starterMethod
OBJA.staticMethod("foo", :returnedCall)
OBJA.new.instanceMethod("bar", :returnedCall)
end
def self.returnedCall(text)
puts text
end
def returnedCall(text)
puts text
end
end
b = OBJB.new
b.starterMethod
--output:--
objA.staticMethod: foo
Call back from objA.staticMethod
objA.instanceMethod: bar
Call back from objA.instanceMethod
您还可以将块传递给OBJA方法:
class OBJA
def self.staticMethod(text, &block)
puts "objA.staticMethod: #{text}"
block.call("Call back from objA.staticMethod")
end
def instanceMethod(text, &block)
puts "objA.instanceMethod: #{text}"
block.call("Call back from objA.instanceMethod")
end
end
class OBJB
def starterMethod
OBJA.staticMethod("foo") {|str| puts str}
OBJA.new.instanceMethod("bar") {|str| puts str}
end
end
b = OBJB.new
b.starterMethod
--output:--
objA.staticMethod: foo
Call back from objA.staticMethod
objA.instanceMethod: bar
Call back from objA.instanceMethod
或者,更多说明关闭:
class OBJA
def self.staticMethod(text, &block)
puts "objA.staticMethod: #{text}"
block.call
end
def instanceMethod(text, &block)
puts "objA.instanceMethod: #{text}"
block.call
end
end
class OBJB
def initialize
@x = 1
@y = 2
end
def starterMethod
OBJA.staticMethod("foo") {puts instance_variable_get(:@x)}
OBJA.new.instanceMethod("bar") {puts instance_variable_get(:@y)}
end
end
b = OBJB.new
b.starterMethod
--output:--
objA.staticMethod: foo
1
objA.instanceMethod: bar
2
我不知道这对你有没有帮助,但这个技巧在整个Ruby框架中都有用。 Ruby是编程语言的狂野西部,它实际上允许你忽略闭包。当您想要接受某些代码中的块时,这很有用,但您不想在定义块的上下文中执行该块 - 而是希望在上下文中执行该块你创造。
class OBJA
@x = 10 #Instance variables attach themselves to whatever object is
@y = 20 #self at the time they are created. Inside a class, but outside
#any defs, self is equal to the class, so these statements
#create what are known as 'class instance variables' (@@variables
#aren't used in ruby because they don't behave 'correctly').
def self.staticMethod(text, &block)
puts "objA.staticMethod: #{text}"
instance_eval &block #See comment (1) below
end
def instanceMethod(text, &block)
puts "objA.instanceMethod: #{text}"
block.call
end
end
class OBJB
def initialize
@x = 1
@y = 2
end
def starterMethod
OBJA.staticMethod("foo") {puts instance_variable_get(:@x)}
OBJA.new.instanceMethod("bar") {puts instance_variable_get(:@y)}
end
end
b = OBJB.new
b.starterMethod
--output:--
objA.staticMethod: foo
10 #<--CHECK THIS OUT!!
objA.instanceMethod: bar
2
(1)当你调用没有接收器的方法时,ruby使用self来调用该方法。在类方法中,self等于类,因此instance_eval()调用等效于:
OBJA.instance_eval &block
instance_eval()用于将自变量的值更改为接收者。但是自己已经等于OBJA了? instance_eval()成功做的是改变它看到的自变量的值!通过将块变量转换为instance_eval的块,实际上可以更改块上下文,即块代码看到的变量。
答案 1 :(得分:1)
目前在类上调用了回调OBJB.send
,但您的returnedCall
方法是实例方法。有两种方法可以解决这个问题:
通过将行OBJB.send(...
更改为
OBJB.new.send(...
或者通过将def returnedCall(...
更改为
def self.returnedCall(text)