2

別のページでこれを見た:

「getterを使用すると、@aの現在の値を変更せずに取得できます。」

「セッターを使用すると、@ aを変更し、その新しい値を戻り値として取得します。」

ただし、cancan wikiからこのコードを見ると、セッターとゲッターの両方が実際にその中の変数に対して何かを行っていることがわかります。

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

ゲッターが実際に真理値を返しているように見えますが、そうでない場合は、少なくともある種の変換が行われます。では、この「ゲッターは変更せずに取得し、セッターは変更を加えて設定する」というルールは実際に正しいのでしょうか。

4

1 に答える 1

7

それは、「ゲッター」と「セッター」について考える間違った方法です。代わりに、次のように考えてください。

セッターは、オブジェクトの状態を変更します。単純なインスタンス変数を設定する場合があります。複数のインスタンス変数を設定する場合があります。投稿されたコードのように、情報を保存する前に変換する場合があります。

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 に答える