最近我一直在阅读“Ruby中的实用面向对象设计”,我注意到最好的做法之一是使用访问器方法而不是直接抓取@instance_variable
。例如:
class Foo
attr_accessor :bar
def initialize(my_argument)
@bar = my_argument
end
# bad
# def lorem_ipsum
# @bar * 999
# end
# good
def lorem_ipsum
bar * 999
end
end
保持DRY是有意义的,如果我需要以某种方式处理@bar
之前实际抓住它的值。但是,我注意到initialize
方法直接设置了@bar
实例变量的值:
class Foo
attr_accessor :bar
def initialize(my_argument)
@bar = my_argument #<-- why isn't self.bar = my_argument used here?
end
这有什么理由吗?是不是应该使用setter方法而不是直接使用=
运算符来设置实例变量的值?
答案 0 :(得分:7)
你是对的,做
会更有意义class Foo
attr_accessor :bar
def initialize(my_argument)
self.bar = my_argument
end
end
关于你是否应该尊重对象本身中的封装的论据不同,但如果你相信,那么,是的,你应该这样做。
答案 1 :(得分:2)
初始化程序在初始化时设置值。访问器允许您在对象已经实例化后通过符号访问(读/写)。
这篇文章可能会帮助您理解: What is attr_accessor in Ruby?
答案 2 :(得分:2)
实际上,setter可以在initialize
中使用,与其他方法相同,但是没有接收器就不能使用setter。
我认为您可以使用a_foo.bar=
或self.bar=
,但如果没有接收方,则无法使用bar=
,因为在后一种情况下,bar
将被视为本地变量而不是setter方法:
class Song
attr_accessor :name
def initialize(name)
self.name = name
end
def test_setter1(value)
@name = value
end
def test_setter2(value)
name = value #name is local variable
end
end
s = Song.new("Mike")
p s
s.test_setter1("John")
p s
s.test_setter2("Rosy")
p s
这导致:
#<Song:0x23a50b8 @name="Mike">
#<Song:0x23a50b8 @name="John">
#<Song:0x23a50b8 @name="John">
答案 3 :(得分:1)
虽然您可以在初始化中使用setter,如@uncutstone's answer所示,但您无法像在代码中的评论中那样使用它。
问题是Ruby会解释:
bar = my_argument
作为bar
局部变量的赋值,而不是bar=
方法的调用。
在“Why do Ruby setters need "self." qualification within the class?”中对此进行了相当广泛的讨论。