2

在另一页看到这个:

“使用 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 实际上正在返回一个真值,如果不是这样,至少是某种转换。那么这个“getter get without modifying, setter set with modified”规则真的是真的吗?

4

1 回答 1

7

这是思考“getter”和“setter”的错误方式。相反,请这样想:

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
于 2012-12-18T00:38:11.110 回答