在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设置有修改”规则实际上是真的吗?
答案 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