加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-17 04:34:54 所属栏目:百科 来源:网络整理
导读:我想用一个用户指定的块替换对象的方法的实现.在 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#中它也很容易 cla
我想用一个用户指定的块替换对象的方法的实现.在 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'

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读