2009-06-09 19 views
1

我有一个包含一些私有属性的类。我想要做的就是动态添加一些setter,仅用于执行特定块。仅扩展一个块调用

的,我想怎样能够例子:

class Content 
    attr_reader :a, :b 

    def initialize 
    @a = 1 
    @b = "plop" 
    end 

    def set(&block) 
    extend(Setter) 
    instance_eval(&block) 
    unextend(Setter) ???? 
    end 

    module Setter 
    def a(value) 
     @a = value 
    end 
    def b(value) 
     @b = value 
    end 
    end 
end 

content = Content.new 
content.set do 
    a 2 
    b "yeah!" 
end 
content.a # should return 2 

编辑:谢谢到目前为止伟大的答案。我澄清了这个问题,因为我实际上需要在类中定义属性读取器,这可能与模块中定义的setter冲突。发布问题时我忘了这部分内容。 (已经晚了^^)

CLARIFICATION:这个类是为DSL写一个配置文件。它针对的是非开发人员,所以操作员越少越好。

我目前使用代理类实现这个,instance_eval块,但我必须与instance_variable_set混乱为了设置值,我不喜欢它。我只是想另一种方式来看看我能否让我的代码更具可读性。

+0

类似有你编写自定义的作家任何理由,而不是使用attr_writer为你生成它们? – rampion 2009-06-10 11:36:58

回答

2
def set(&block) 
    extend(Setter) 
    instance_eval(&block) 
    Setter.instance_methods.each do |m| 
     instance_eval "undef #{m}" 
    end 
    end 

,我不知道会为你做的任何方法,但可能有些东西..这应该做的工作,虽然,通过寻找二传手的所有实例方法和内容取消定义他们。

+0

更有效地执行instance_eval {undef m}。 – Chuck 2009-06-09 22:07:42

+0

不起作用,因为undef需要'm'作为文字,而不是评估它......虽然可以做instance_eval {undef:“#{m}”}但我认为这并不明显。 – cloudhead 2009-06-09 23:06:00

3

在Ruby中没有原生的“未扩展”模块。 mixology gem将此模式实现为C(和Java,用于JRuby)扩展,创建mixinunmix方法。但是,如果您需要Ruby 1.9支持,您可能需要应用patch

如果您更愿意避免使用第三方库,另一种方法可能只是使制定者专用:

class Content 
    def initialize 
    @a = 1 
    @b = "plop" 
    end 

    def set(&block) 
    instance_eval(&block) 
    end 

    private 

    def a(val) 
    @a = val 
    end 

    def b(val) 
    @b = val 
    end 

end 

content = Content.new 

#This will succeed 
content.set do 
    a 2 
    b "yeah!" 
end 

# This will raise a NoMethodError, as it attempts to call a private method 
content.a 3 
0

,如果你在一个实验性的情绪感觉还检查了:dup_eval

它在某些方面mixico但也有一些有趣的附加功能(object2module