我想为一个类创建一个工厂,它将调用一个私有的setter。这可能吗?
这样做:
class Foo
def self.from_bar(bar)
f = new bar.foo_id # bar has the id of the foo object I want to make
f.bar = bar # but I also wanna store the bar object in foo
f
end
def initialize(id)
end
private
attr_writer :bar
# lazily load and memoize bar if needed and construction was not
# made from factory method
def bar
@bar ||= ...
end
end
导致NoMethodError: private method
错误。我可以send
这个方法,但我正在寻找一种非黑客的方法。
编辑:将attr_accessor更改为attr_writer并添加了memoized reader以显示我的更多意图。
答案 0 :(得分:1)
是的,这是可能的。
Ruby允许您使用send
方法从任何地方调用私有方法。
你的工厂看起来像这样:
class FooFactory
def FooFactory.build(bar)
foo = Foo.new(generate_id)
foo.send('bar=', bar)
foo
end
private
def generate_id
rand(999999)
end
end
然后简单地致电:
FooFactory.build('bar')
请注意,这是工厂的标准模式,发送行也可以在您的代码段中使用。
答案 1 :(得分:1)
这只有采用hacky方法才有可能:
class Foo
def self.from_bar(bar)
new(bar.foo_id).tap { |f| f.send(:bar=, bar) }
# or, better:
new(bar.foo_id).tap { |f| f.instance_variable_set(:@bar, bar) }
end
private
attr_accessor :bar
end
老实说,让attr_accessor
私有化有点意义。
答案 2 :(得分:1)
重新阅读这个问题后,我相信这可能就是答案。
我得出结论,不需要工厂,这可以在初始化方法中完成。
class Foo
def initialize(id, bar)
@id = id
@bar = bar
end
end
注意:然后您可以使用attr_reader访问栏。这将定义bar
但不定义bar=
。
attr_reader :bar