在Ruby中定义访问器时,在简洁(我们都喜欢)和最佳实践之间可能存在矛盾。
例如,如果我想公开一个示例上的值,但禁止任何外部对象更新它,我可以执行以下操作:
class Pancake
attr_reader :has_sauce
def initialize(toppings)
sauces = [:maple, :butterscotch]
@has_sauce = toppings.size != (toppings - sauces).size
...
但是突然间我使用了一个原始示例变量,这让我很紧张。我的意思是,如果我需要在将来的某个日期设置之前处理has_酱料,我可能需要做更多的重构,而不仅仅是覆盖访问器。拜托,原始示例变量?废话。
我可以忽略这个问题,使用attr_accessor
。我的意思是,任何人都可以设置属性,如果他们真的想;这毕竟是Ruby,但是我失去了数据封装的概念,对象的接口定义得不太好,系统可能会更加混乱。
另一个解决方案是在不同的访问修饰符下定义一对访问器:
class Pancake
attr_reader :has_sauce
private
attr_writer :has_sauce
public
def initialize(toppings)
sauces = [:maple, :butterscotch]
self.has_sauce = toppings.size != (toppings - sauces).size
end
end
这样就完成了任务,但对于一个简单的访问器来说,这是一个样板文件,坦率地说:好恶心
那么,有没有更好、更Ruby的方式呢?
5条答案
按热度按时间fafcakar1#
private
可以接受一个符号arg,所以...或
等等。
但是“原始”示例变量有什么问题呢?它们是示例内部的;唯一能用名字来调用它们的代码是
pancake.rb
中的代码,这是你的。2它们以@
开头,我想这会让你说“blech”,这是它们私有的原因。3如果你愿意,可以把@
看作private
的简写。至于处理,我想你的直觉是好的:如果可以,请在构造函数中进行处理;如果必须,请在自定义访问器中进行处理。
tyu7yeag2#
attr_reader
等只是方法-没有理由定义变量供自己使用(我同意你的观点)例如:然后使用
private_accessor
,就像使用attr_accessor
一样(我认为您需要一个比private_accessor更好的名称)bhmjp9jg3#
您可以将
attr_reader
放在private
范围中,如下所示:这将引发预期的错误:
avwztpqn4#
在类中直接引用示例变量并没有什么错。无论是将这些方法设置为public还是private,
attr_accessor
都只是间接引用。在这个特殊的例子中,它可能有助于识别
toppings
可能是一个您想要保存用于其他目的的属性,而has_sauce
是一个“虚拟属性”,一个依赖于底层浇头属性的模型特征。像这样的东西可能会感觉更干净:
是否也公开
attr_accessor :toppings
由您决定。如果您只是把浇头扔掉,那么您的类就不太像Pancake
,而更像PancakeToppingDetector
;)jgwigjjp5#
Ruby 3.0 made access modifiers and
attr_*
work with each other,因此您可以直接写入