Techioz Blog

Ruby クラスの属性を理解し、アクセサー マクロと self を使用する

概要

そこで、Ruby でクラスを作成します。

class User
  def initialize
  end
end

ここで、ゲッター/セッターを使用してハッシュである属性を作成したいとします。これを行うためのオプションについて混乱しています。

これを行うと:

class User
  attr_accessor :some_hash
end

しかし、このハッシュが nil になることは望ましくなく、常に空のハッシュになります。

いつやるべきか迷っています:

def some_hash
  self.some_hash ||= {}
end

そして、やります:

def some_hash
  @some_hash ||= {}
end

違いはなんですか?

attr_accessor を使用しない場合は、リーダーとライター (またはゲッター/セッター) の両方を作成する必要があります。

def some_hash=()
end

def some_hash
end

ハッシュである some_hash 属性を作成するためのオプションを誰かが明確にしてくれ、それが空の場合は決して nil を返さないことを願っています。

つまり、attr_accessor を使用し、メソッドを手動で作成し、最後に @some_hash と self.some_hash をいつ使用するかです。

解決策

attr_accessor :some_hash は、指定された属性のリーダーおよびライター メソッドを定義します。これは次と同等です。

class User
  def some_hash
    @some_hash
  end

  def some_hash=(a_hash)
    @some_hash = a_hash
  end
end

@some_hash はオブジェクトのインスタンス変数を参照し、some_hash と some_hash= はメソッドです。前者は変数の値を返し、後者は変数を設定します。

イディオム self.some_hash ||= {} は self.some_hash || と同等です。 self.some_hash = {}。

Ruby のブール演算子はショートサーキットです。つまり、最初の式 (self.some_hash) が true 値を返した場合、2 番目の式 (self.some_hash = {}) はまったく実行されません。

方法:

def some_hash
  self.some_hash ||= {}
end

some_hash || に展開されるため、実際には再帰的です。 self.some_hash = {}。スタック オーバーフローが発生するまで、自身を呼び出し続けます。 2 番目の形式を使用します。

def some_hash
  @some_hash ||= {}
end

インスタンス変数を直接設定するため、再帰の問題は発生せず、ライター メソッドを呼び出す必要もありません。 @some_hash が nil の場合、メソッドが戻る前に空のハッシュが割り当てられるため、some_hash は nil を返すことはできません。

ちなみに、変数は User インスタンスの作成時ではなく、最初にアクセスされたときに初期化されるため、これは遅延初期化とも呼ばれます。