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

Ruby getter真的不修改实例变量吗?,ruby,getter-setter,Ruby,Getter Setter,我在电视上看到这个: 使用getter,可以获得@a的当前值,而无需修改它 使用setter,可以修改@a,并将其新值作为返回值 然而,从中查看这段代码,我发现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|

我在电视上看到这个:

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

使用setter,可以修改@a,并将其新值作为返回值

然而,从中查看这段代码,我发现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无需修改即可获取,setters设置需修改”规则是否真的成立?

这是错误的看待“getter”和“setters”的方式。相反,你可以这样想:

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

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

通常建议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

那么它就不必返回实例变量了?第二个方法返回的是真值,对吗?它不一定是“简单”的实例变量表达式(例如
@a
)。getter/setter实际上将一系列角色编码/解码为一个内部整数(其中每个角色由一个特定的“位”表示);这样就避免了必须在阵列周围。getter返回一个数组,因为它将整数“分解”回相应的序列。