getter真的不能修改实例变量吗?

Dre*_*ush 2 ruby getter-setter

另一页上看到这个:

"使用getter,可以获得@a的当前值,而无需修改它."

"使用setter,one修改@a,并将其新值作为返回值."

但是,从cancan wiki查看这段代码,我发现setter和getter实际上都在为它中的变量做些什么.

def roles=(roles)
  self.roles_mask = (roles & ROLES).map { |r| 2**ROLES.index(r) }.inject(0, :+)
end

def roles
  ROLES.reject do |r|
    ((roles_mask || 0) & 2**ROLES.index(r)).zero?
  end
end
Run Code Online (Sandbox Code Playgroud)

看起来getter实际上是返回一个真值,如果不是,那么至少是某种变换.那么这个"getters得到了没有修改,setter设置与修改"规则实际上是真的吗?

小智 7

这是考虑"吸气剂"和"制定者"的错误方式.相反,想一想:

setter 改变对象的状态.它可能设置一个简单的实例变量.它可能会设置几个实例变量.与发布的代码一样,它可能会在保存之前转换信息.

getter 检索有关对象状态的一些信息.这是什么并不重要; 它可以是直接存储在实例变量中的值.或者它可以是基于对象的当前状态的一些其他值,如在帖子中.

通常建议getter和setter采用/返回相同类型的值,并以一致的方式影响/报告对象状态.在上面,暴露类型是"角色数组",它代表与对象相关的角色.


使用额外命名的方法可以更清楚地显示发布代码的意图,因为可以提取出复杂的位掩码构建/消费表达式; 注意对称性:

def toMaskFromArray (roles)
  (roles & ROLES).map { |r| 2**ROLES.index(r) }.inject(0, :+)
end

def toArrayFromMask (mask)
  ROLES.reject do |r|
    ((mask || 0) & 2**ROLES.index(r)).zero?
  end
end

def roles=(roles)
  self.roles_mask = toMaskFromArray(roles)
end

def roles
  toArrayFromMask(self.roles_mask)
end
Run Code Online (Sandbox Code Playgroud)