【问题标题】:What is the difference between an instance method used to rename an object and a setter method?用于重命名对象的实例方法和 setter 方法有什么区别?
【发布时间】:2019-11-13 01:24:32
【问题描述】:

如果我想重命名下面的jedi 对象,为什么要创建一个名为rename 的实例方法,它使用setter 方法name=?为什么不直接使用setter方法`name='呢?

为什么这样做:

     class Skywalker
       attr_accessor :name

       def initialize(name)
         @name = name
       end

       def rename(new_name)
         self.name = new_name
       end
     end

     jedi = Skywalker.new('Anakin')
     puts jedi.name
     jedi.rename('Luke')
     puts jedi.name

什么时候可以这样做:

     class Skywalker
       attr_accessor :name

       def initialize(name)
         @name = name
       end
     end

     jedi = Skywalker.new('Anakin')
     puts jedi.name
     jedi.name = 'Luke'
     puts jedi.name

上面的两个代码 sn-ps 都做同样的事情,所以我想知道除了 setter 方法 name= 之外,是否有实例方法 rename 会很有用。因为在我看来它们是多余的。

【问题讨论】:

  • 您确实不需要同时使用它们。出于可读性考虑,您可能希望选择其中一个(以更好地表达您的意图)
  • 请注意,您可以将rename 的定义替换为alias :rename :name=(尽管正如@Sergio 所说,两者兼有没有意义)。你是想写instance.name = ... 还是instance.rename(...) 纯粹是主观的。如果jedi = Skywalker.new('Anakin')(jedi = 'Bob').upcase #=> "BOB"jedi.rename('Bob').upcase #=> "BOB" 相比可能看起来有点奇怪,但两者都能完成工作。

标签: ruby oop methods instance setter


【解决方案1】:

#rename 隐藏了实现细节。您公开了一个干净且显式的接口 - 可以重命名一个对象,但调用者不必关心它是如何完成的。我建议使用attr_reader :name 而不是attr_accessor :name 以避免暴露setter。

如果您只公开#name=,您就可以让调用者更改对象内部结构。它可能会导致未来的变化更加困难(例如,如果您将 name 移动到单独的对象)。

【讨论】:

  • “你让调用者改变对象内部”——不一定。只是一个方法,和rename一样。如果要将 @name 的存储移动到其他地方,则不需要此公共 api。我同意rename 可能会更好地传达意图,但值得付出努力吗?由 OP 决定:)
  • 你说得对,setter 只是一个方法。还是rename 听起来更好:)
猜你喜欢
  • 2010-11-06
  • 1970-01-01
  • 1970-01-01
  • 2015-04-18
  • 1970-01-01
  • 1970-01-01
  • 2015-05-02
  • 2015-02-04
  • 2021-03-25
相关资源
最近更新 更多