问题 为什么初始化时没有使用setter方法?


最近我一直在阅读“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

保持干燥是有意义的,以防我需要处理 @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方法而不是直接使用 = operator设置实例变量的值?


3019
2017-12-12 15:24


起源



答案:


你是对的,这样做会更有意义

class Foo
  attr_accessor :bar

  def initialize(my_argument)
    self.bar = my_argument
  end
end

关于是否应该尊重封装,参数不同  对象本身与否,但如果你相信,那么,是的,你应该这样做。


6
2017-12-12 15:40



“如果你相信这一点,那么,是的,你应该这样做。”并且在你的代码中始终如一地做到这一点,否则当你未来的自我想知道为什么你不一致时会让人感到困惑。 - the Tin Man


答案:


你是对的,这样做会更有意义

class Foo
  attr_accessor :bar

  def initialize(my_argument)
    self.bar = my_argument
  end
end

关于是否应该尊重封装,参数不同  对象本身与否,但如果你相信,那么,是的,你应该这样做。


6
2017-12-12 15:40



“如果你相信这一点,那么,是的,你应该这样做。”并且在你的代码中始终如一地做到这一点,否则当你未来的自我想知道为什么你不一致时会让人感到困惑。 - the Tin Man


初始化程序在初始化时设置值。访问器允许您在对象已实例化后通过符号访问(读/写)。

这篇文章可能会帮助您理解: 什么是Ruby中的attr_accessor?


2
2017-12-12 15:28



当然,您可以在初始化程序中使用setter。 - Jörg W Mittag
你能详细说说吗?你是什​​么意思在初始化器中使用setter?如果初始化程序已经可以访问变量,为什么还需要这样做呢? - Justus Eapen
本书不遗余力地解释你总是应该使用setter和getter并且永远不会直接访问实例变量,但是它在初始化器中明显地忽略了它自己的建议。但初始化程序只是一种方法,就像任何其他方法一样,所有相同的原因都完全相同。 - Jörg W Mittag


实际上,可以使用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">

2
2017-12-12 16:00





虽然你可以在初始化中使用setter,如图所示 @ uncutstone的回答,您不能像在代码中的注释中那样使用它。

问题是Ruby会解释:

bar = my_argument

作为一个任务 bar 局部变量而不是调用 bar= 方法。

这在“相当广泛的讨论中”为什么Ruby setter需要“自我”。课堂上的资格?”。


1
2017-12-12 15:53



对不起,我打算使用self.bar,更新问题 - Edmund