gpt4 book ai didi

ruby - 在 Ruby 中动态替换对象上的方法实现

转载 作者:数据小太阳 更新时间:2023-10-29 06:51:58 24 4
gpt4 key购买 nike

我想用用户指定的 block 替换对象方法的实现。在 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> 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");

但是我怎样才能在 Ruby 中做同样的事情呢?我有一个将 lambda 存储在实例变量中并且该方法调用 lambda 的解决方案,但我不太喜欢开销和语法

class Foo
def initialize
@bar = lambda {|x| puts x}
end

def bar x
@bar.call x
end

def bar= blk
@bar = blk
end
end

foo = Foo.new
foo.bar "baz"
foo.bar= lambda {|x| puts "*" + x.to_s}
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 方法,但我也不喜欢那样:)。

class Foo
def bar x
if (@bar.nil?)
puts x
else
@bar.call x
end
end

def set_bar &blk
@bar = blk
end
end

所以问题是:是否有更好的方法来做到这一点,如果没有,您更喜欢哪种方法

编辑:@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"

是的,就这么简单

编辑:为了不丢失范围,您可以使用 define_singleton_method(如@freemanoid 的回答):

 prefix = "*"

foo.define_singleton_method(:bar) do |x|
puts prefix + x.to_s
end

foo.bar 'baz'

关于ruby - 在 Ruby 中动态替换对象上的方法实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9786495/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com