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

时间:2012-12-18 00:35:53

标签: ruby getter-setter

another page上看到了这个:

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

“使用setter,一个修改@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

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

1 个答案:

答案 0 :(得分:7)

这是考虑“吸气者”和“定位者”的错误方式。相反,想一想:

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

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

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


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

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