Ruby中对象的动态替换方法实现
我想用用户指定的块替换对象方法的实现。在JavaScript中,这很容易实现:Ruby中对象的动态替换方法实现,ruby,metaprogramming,Ruby,Metaprogramming,我想用用户指定的块替换对象方法的实现。在JavaScript中,这很容易实现: function Foo() { this.bar = function(x) { console.log(x) } } foo = new Foo() foo.bar("baz") foo.bar = function(x) { console.error(x) } foo.bar("baz") 在C#中也很容易 class Foo { public Action<string> Ba
function Foo() {
this.bar = function(x) { console.log(x) }
}
foo = new Foo()
foo.bar("baz")
foo.bar = function(x) { console.error(x) }
foo.bar("baz")
在C#中也很容易
class Foo
{
public Action<string> Bar { get; set; }
public Foo()
{
Bar = x => Console.WriteLine(x);
}
}
var foo = Foo.new();
foo.Bar("baz");
foo.Bar = x => Console.Error.WriteLine(x);
foo.Bar("baz");
我想要这样的语法:
foo.bar do |x|
puts "*" + x.to_s
end
foo.bar "baz"
我想出了以下代码
class Foo
def bar x = nil, &blk
if (block_given?)
@bar = blk
elsif (@bar.nil?)
puts x
else
@bar.call x
end
end
end
但对于不止一个参数来说,这有点难看,而且仍然感觉不“正确”。我还可以定义一个set_bar方法,但我也不喜欢:)
所以问题是:有没有更好的方法来做到这一点,若并没有,你们会选择什么方法
编辑:
@welldan97的方法是有效的,但我放宽了局部变量范围,即
prefix = "*"
def foo.bar x
puts prefix + x.to_s
end
不起作用。我想我必须坚持使用lambda才能工作?使用def
:
foo = Foo.new
foo.bar "baz"
def foo.bar x
puts "*" + x.to_s
end
foo.bar "baz"
是的,很简单
编辑:为了不失去范围,您可以使用定义单例方法
(如@freemanoid-answer中所示):
您可以像这样实现您想要的:
class Foo; end
foo = Foo.new
prefix = '*'
foo.send(:define_singleton_method, :bar, proc { |x| puts prefix + x.to_s })
foo.bar('baz')
"*baz" <<<<<-- output
Foo类;结束
foo=foo.new
前缀='*'
send(:define_singleton_method,:bar,proc{x|put prefix+x.to_s})
foo.bar(“baz”)
“*baz”哦,那可能太简单了*facepalm*:)嗯,我把范围放宽到了局部变量,即prefix=“*”;def foo.bar x;将前缀+x置于_;end
不起作用:/@welldan97,我如何替换特定对象的方法“setter”?@gaussblurinc,如果你想重新定义其中一个setter方法,它几乎是相同的foo={};foo.define_singleton_方法(:bar=){x | self[:bar]=x};foo.bar=5;如果我没弄错你说的话want@welldan97是的,你明白我的意思。但我现在无法理解你:)你创建的是一个结构,而不是一个对象。我的意思是我想为特定对象而不是结构重新定义方法“setter”
foo = Foo.new
foo.bar "baz"
def foo.bar x
puts "*" + x.to_s
end
foo.bar "baz"
prefix = "*"
foo.define_singleton_method(:bar) do |x|
puts prefix + x.to_s
end
foo.bar 'baz'
class Foo; end
foo = Foo.new
prefix = '*'
foo.send(:define_singleton_method, :bar, proc { |x| puts prefix + x.to_s })
foo.bar('baz')
"*baz" <<<<<-- output