Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby中对象的动态替换方法实现_Ruby_Metaprogramming - Fatal编程技术网

Ruby中对象的动态替换方法实现

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

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

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