【问题标题】:Perform method after select variable assignments in Ruby在 Ruby 中选择变量赋值后执行方法
【发布时间】:2012-01-09 07:09:54
【问题描述】:

我正在尝试干掉一些代码,我觉得 Ruby 的变量赋值必须提供一种简化它的方法。我有一个定义了许多不同实例变量的类。其中一些旨在隐藏(或只读),但许多是公开的,具有读/写访问权限。

对于所有具有公共写访问权限的变量,我想在每次赋值后执行某种方法。我知道,一般来说,我可以这样做:

def foo=(new_foo)
    @foo = new_foo
    post_process(@foo)
end

def bar=(new_bar)
    @bar = new_bar
    post_process(@foo)
end

但是,似乎应该有一个很好的方法来干燥它,因为我在每次赋值后都在做基本上相同的事情(即运行相同的方法,并将新分配的变量作为参数传递给那个方法)。因为我有很多这样的变量,所以有一个通用的解决方案会很棒。

【问题讨论】:

    标签: ruby variable-assignment dry


    【解决方案1】:

    更简单的解决方案

    如果您批量分配这些变量,您可以执行以下操作:

    kv_pairs = {:foo => new_foo_value,
      :bar => new_bar_value}
    
    kv_pairs.each do |k, v|
      self.send(k.to_s + '=', v)
      post_process(v)
    end
    

    元编程

    这里有一些红宝石魔法:-)

    module PostProcessAssignments
      def hooked_accessor( *symbols )
        symbols.each { | symbol |
          class_eval( "def #{symbol}() @#{symbol}; end" )
          class_eval( "def #{symbol}=(val) @#{symbol} = val; post_process('#{symbol}', val); end" )
        }
      end
    end
    
    class MyClass
      extend PostProcessAssignments
    
      hooked_accessor :foo
    
      def post_process prop, val
        puts "#{prop} was set to #{val}"
      end
    
    
    end
    
    mc = MyClass.new
    mc.foo = 4
    puts mc.foo
    

    输出:

    foo was set to 4
    4
    

    【讨论】:

    • 不幸的是,我不能指望这些变量一起重新分配,所以允许人们直接执行 my_var.foo = new_value 会很好。也就是说,这给了我一个想法——也许有一种方法可以同时重载所有相关变量的 '=' 方法,然后使用 .to_s 来处理分配。不幸的是,我对 Ruby 中的(元)编程知之甚少,无法准确地做到这一点。
    • 哈,是的,我认为我们的编辑越界了。这看起来很光滑。但是, hooked_accessor :foo 行仍然让我感到困惑。 mc.foo 如何知道在正确的时间调用 hooked_accessor?它只是类似于调用 attr_accessor :foo 的方式吗?
    • 另外,在 Ruby 中使用 class_eval 有什么安全问题吗?
    • 使用hooked_accessor 替代attr_accessor。安全问题?不要这么想。一些名称冲突是可能的,但避免它是微不足道的。
    猜你喜欢
    • 2015-09-19
    • 1970-01-01
    • 2015-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-24
    • 2019-01-17
    • 1970-01-01
    相关资源
    最近更新 更多