我在很多代码中看到的东西:
class Foo
attr_accessor :bar
# lots of code omitted
def baz
'qux' if bar
end
end
baz方法的确切形式并不太重要 - 这里只是bar
是对实例变量@bar
的getter方法的引用,从实例的类中调用。我倾向于明确地从@bar
检索值。对此有何意见?
我从未在ruby style guide或类似内容中看到任何内容。我个人觉得做前者会让人更难阅读和理解,特别是当课程超过几百行时。
修改
也许为了说明我认为这个设计的尴尬,让我们重新评估一个非常标准的初始化方法:
class Foo
attr_accessor :bar, :qux
def initialize(bar, qux)
@bar = bar
@qux = qux
end
end
如果我们使用setter方法,我们不能通过类比使用bar = ?
。相反,我们有:
class Foo
attr_accessor :bar, :qux
def initialize(bar, qux)
self.bar = bar
self.qux = qux
end
end
失去了第一个优雅的一些。我们有一个更灵活的设计,因为我们现在可以自由地重写我们的setter方法并取消attr_writer
。但我只是在风格方面有一些观点,感觉很像配置而不是相反,而Russ Olsen已经宣称设计'模式'不仅仅是Rails而是Ruby也是如此。
答案 0 :(得分:5)
通过getter访问属性具有提供封装的优势。在某些方面,使用实例变量来存储值是一个实现细节。当然,情况是否合适。但是,我不记得读过任何明确的这种风格问题了。
找到https://softwareengineering.stackexchange.com/questions/181567/should-the-methods-of-a-class-call-its-own-getters-and-setters,从与语言无关的角度讨论该问题。还发现https://www.ruby-forum.com/topic/141107,这是特定于ruby的,虽然它没有打破任何新的基础,更不用说暗示Ruby标准了。
更新:刚刚在http://www.amazon.com/Practical-Object-Oriented-Design-Ruby-Addison-Wesley/dp/0321721330/ref=sr_1_1?s=books&ie=UTF8&qid=1376760915&sr=1-1第24页发表了以下声明,这是一本备受推崇的关于Ruby的书:“隐藏变量,甚至来自定义它们的类,用方法包装它们。“ (重点补充)。它继续使用访问器方法提供类中方法的示例。
答案 1 :(得分:2)
我赞成明确地从@bar中检索值。有没有 对此的看法?
是的,直接访问不如设计灵活。 getter和setter可用于转换值。这就是为什么java程序员花费一半的时间来为他们的私有变量做出任何不做任何setter和getter的事情 - 他们希望将setter和getter作为他们的api,这允许他们在将来改变他们的代码来改变路上的值在不改变api的情况下进出。
然后ruby带来了整洁的attr_accessor方法,这意味着写作什么都不做,而且getter不再是痛苦的。
Python更进了一步。在python中,实例变量是公共的,你可以直接访问它们,例如
print my_dog.age
编写python程序的java程序员将实现get_age()和set_age()方法:
class Dog:
def get_age(self):
return self.age
def set_age(self, age):
self.age = age
然后,java程序员将飞越该地区的所有城镇,并将描述getter和setter方法的传单作为获取和设置age实例变量的api,并且他们会警告人们不要直接访问实例变量 - - 或者其他事情可能会破裂。
然而,python有一个功能,允许程序员消除getter和setter,直到他们真正需要做一些有用的事情 - 而不是愚蠢地获取或设置一个值。 Python允许您将客户端代码对实例变量的直接访问转换为方法调用。对客户来说它是透明的。例如,客户端代码可能通过写:
来访问类中的实例变量my_dog.age
Python允许类的编写者随后实现一个名为age()的方法,并且my_dog.age可以调用该方法而不是直接访问实例变量(请注意,在python中,与ruby不同,你可以通常在没有括号的情况下调用方法。然后,新实现的age()方法可以在将其返回到客户端代码之前对age实例变量执行任何操作。将其转化为人类年,或从数据库中检索年龄。
答案 2 :(得分:1)
实际上是faster to use a getter,主要是因为attr_reader
和attr_accessor
是用C而不是Ruby编写的。
作为已经编写Ruby几年的人,我认为使用attr_*
更具可读性。但这可能只是我已经习惯的东西。