2
3

More than 3 years have passed since last update.

initializeメソッドとattr_accessorについて

Posted at

 初学者の私がRubyを学ぶ上でまず躓いたのがattr_accessorやinitializeメソッドだったので自分の中の整理の意味も含めて書いておきたいと思います。

attr_accessorを理解するためにはinitializeメソッドの理解が必要だと思うので先にそちらから書いていきます!因みに今回は例のポケモンを使って説明していきたいと思います。

目的

・ポケモン(Pokemon)というクラスを元に基本的な情報であるステータス(名前、体力、攻撃力、防御力)を持つリザードン(lizardon)を生み出す。(何でリザードン?かっこいいからにきm)

本編

1. クラス設定

まず、クラスの設定を行います。


class Pokemon

end

まずはクラスの定義からですね。ここからリザードンに必要な情報を書いていきます。

2. ステータスの設定(セッターの定義)

 リザードンには名前(name)、体力(hp)、攻撃力(offense)、防御力(defense)の4つのステータスが存在しますので設定していきましょう。まず覚えるべき言葉が「セッター」です。セッターとは、簡単にいうと、ステータスの値を更新するためのメソッドです。

例えば、体力の更新するときはlizardon.hp = 500のように = を用いて値を代入します。そのため、メソッドを定義する際にもhp =(hp)の形で記述することになります。

class Pokemon
  # nameのセッター
  def name=(name)
    @name = name
  end

  # hpのセッター
  def hp=(hp)
    @hp = hp
  end

  # offenseのセッター
  def offense=(offense)
    @offense = offense
  end

  # defenseのセッター
  def defense=(defense)
    @defense = defense
  end

end

hp = (hp)(hp)は引数と呼ばれます。この引数に渡ってきた値がインスタンス変数@hpに格納されます。もう少し具体的にみていきます。

class Pokemon

  def name=(name)
    @name = name
  end

  def hp=(hp)
    @hp = hp
  end

  def offense=(offense)
    @offense = offense
  end

  def defense=(defense)
    @defense = defense
  end

end

# ポケモンクラスをインスタンス化(lizardonが誕生)
lizardon = Pokemon.new

# lizardonのステータスに値を設定
lizardon.name = "リザードン"
lizardon.hp = 78
lizardon.offense = 84
lizardon.defense = 78

インスタンス化というのは、ポケモンクラスからステータスも何もを持たないまっさらなlizardonが新しく生まれたと考えてください。そして、ステータスの設定で値が決まり、それがセッターの引数に渡され、最終的にインスタンス変数に渡るイメージです。

こうすることで各ステータスの値がインスタンス変数にセットされます。(故にセッター!)

3. ステータスの取得(ゲッターの定義)

 セッターでは、リザードンのステータスの設定ができました。が、これではまだ値をセットしただけにすぎません。折角セットした値ですがこれを取り出すことができないと意味ないですね。そこで今回はこの値をゲットするという意味での「ゲッター」を作っていきましょう!

class Pokemon

  def name=(name)
    @name = name
  end

  # nameのゲッター
  def name
    @name
  end

  def hp=(hp)
    @hp = hp
  end

  # hpのゲッター
  def hp
    @hp
  end

  def offense=(offense)
    @offense = offense
  end

  # offenseのゲッター
  def offense
    @offense
  end


  def defense=(defense)
    @defense = defense
  end

  # defenseのゲッター
  def defense
    @defense
  end

end

ゲッターを定義できたので、実際に取り出してみましょう。

class Pokemon

  def name=(name)
    @name = name
  end

  # nameのゲッター
  def name
    @name
  end

  def hp=(hp)
    @hp = hp
  end

  # hpのゲッター
  def hp
    @hp
  end

  def offense=(offense)
    @offense = offense
  end

  # offenseのゲッター
  def offense
    @offense
  end


  def defense=(defense)
    @defense = defense
  end

  # defenseのゲッター
  def defense
    @defense
  end

lizardon = Pokemon.new

lizardon.name = "リザードン"
lizardon.hp = 78
lizardon.offense = 84
lizardon.defense = 78

# 値を取り出す
puts lizardon.name
puts lizardon.hp
puts lizardon.offense
puts lizardon.defense

end

実行画面

リザードン
78
84
78

ゲッターを利用して値を取り出すことができましたね!

4. initializeメソッド

 さて、いよいよinitializeメソッドについての説明です。ここまで理解できていたらそこまで難しくありません!initializeメソッドを簡単に説明すると、初期値の設定をするためのメソッドです。 

具体的には次のようにします。


#初期値の設定
  def initialize
   @name = "リザードン"
   @hp = 78
   @offense = 84
   @defense = 78
  end

初期値の設定、これは実はさっきまでのコードで既に行っていました。該当の箇所はここです。


# lizardonのステータスに値を設定
lizardon.name = "リザードン"
lizardon.hp = 78
lizardon.offense = 84
lizardon.defense = 78

なのでこちらの部分はカットして、それに伴うセッターもカットしてしまいましょう。

class Pokemon

#初期値の設定
  def initialize
   @name = "リザードン"
   @hp = 78
   @offense = 84
   @defense = 78
  end

#ゲッターは残しておく
  def name
    @name
  end

  def hp
    @hp
  end

  def offense
    @offense
  end

  def defense
    @defense
  end

# ポケモンクラスをインスタンス化(lizardonが誕生)
lizardon = Pokemon.new

# 値を取り出す
puts lizardon.name
puts lizardon.hp
puts lizardon.offense
puts lizardon.defense

end

因みに、このinitializeメソッドはnewメソッドでインスタンス化することでインスタンス変数に初期値がセットされますので忘れずにインスタンス化しましょう。

5. 自由なパラメータ設定

 ここまでの内容では、initializeメソッドは決まった値しかパラメータを設定できません。これを好きな値に変えてみたいと思います。

次のようにして準備しましょう!

各インスタンスごとに柔軟に値を設定できるように書き換えてみましょう。その際は、new演算子に引数を渡して値を設定します。

class Pokemon

# new演算子から渡された引数を受け取る
  def initialize(name:, hp:, offense:, defense:)
   @name = name
   @hp = hp
   @offense = offense
   @defense = defense
  end

  def name
    @name
  end

  def hp
    @hp
  end

  def offense
    @offense
  end

  def defense
    @defense
  end

# パラメータの値をinitializeにキーワード引数として渡す
lizardon = Pokemon.new(name: "リザードン", hp: 78, offense: 84, defense: 78)

puts lizardon.name
puts lizardon.hp
puts lizardon.offense
puts lizardon.defense

end

initializeに渡す引数はnew演算子において {name: "リザードン", hp: 78, offense: 84, defense: 78} というようなハッシュの形式(キーとバリューの組み合わせ)となっています。そのため、initializeに渡す引数もハッシュ形式で渡してあげましょう!
次のように書き換えられます。

class Pokemon

# 引数に**を記述:ハッシュしか受け取れなくなる
  def initialize(**params)
   @name = params[:name]
   @hp = params[:hp]
   @offense = params[:offense]
   @defense = params[:defense]
  end

  def name
    @name
  end

  def hp
    @hp
  end

  def offense
    @offense
  end

  def defense
    @defense
  end

# パラメータの値をinitializeにキーワード引数として渡す
lizardon = Pokemon.new(name: "リザードン", hp: 78, offense: 84, defense: 78)

puts lizardon.name
puts lizardon.hp
puts lizardon.offense
puts lizardon.defense

end

こうすることでミスが起こりにくい記述になります。

6. アクセスメソッド(attr_reader)

 実はこれまでに書いてきたセッターやゲッターの処理はもっと簡潔に記述できます。それがアクセスメソッドです。

先ほどのコードを次のように直してみましょう。

class Pokemon

# attr_readerの記述でゲッターを省略することができる
  attr_reader :name, :hp, :offense, :defense

  def initialize(**params)
   @name = params[:name]
   @hp = params[:hp]
   @offense = params[:offense]
   @defense = params[:defense]
  end

lizardon = Pokemon.new(name: "リザードン", hp: 78, offense: 84, defense: 78)

puts lizardon.name
puts lizardon.hp
puts lizardon.offense
puts lizardon.defense

end

次のような結果になるはずです。

リザードン
78
84
78

attr_readerはゲッターの役割を果たすことが理解できたかと思います。

7. アクセスメソッド(attr_writer)

これで一旦、リザードンの初期パラメーターは表現できました。しかし、もう少し一工夫しましょう。リザードンのHPは敵から受けるダメージによって変化する可能性がありますよね?そのためHPの初期値から値が変化するようにコードを書き直していきましょう。

class Pokemon

  attr_reader :name, :hp, :offense, :defense

  def initialize(**params)
   @name = params[:name]
   @hp = params[:hp]
   @offense = params[:offense]
   @defense = params[:defense]
  end

# セッターを再定義
  def hp=(hp)
    @hp = hp
  end

lizardon = Pokemon.new(name: "リザードン", hp: 78, offense: 84, defense: 78)

puts lizardon.name
puts lizardon.hp
puts lizardon.offense
puts lizardon.defense

lizardon.hp -= 30

puts "#{lizardon.name}はダメージを受けた! 残りHPは#{lizardon.hp}だ"

end

ここでセッターをまた定義することで lizardon.hp -= 30によってHPの初期値(78)から30引かれた値(48)が再セットされます。

つまり最後の出力は次のようになるはずです。


リザードンはダメージを受けた! 残りHP48

この流れをもっと簡潔にするためのものがattr_writerです。

class Pokemon

  attr_reader :name, :hp, :offense, :defense
# attr_writerでセッターを定義
  attr_witer :hp

  def initialize(**params)
   @name = params[:name]
   @hp = params[:hp]
   @offense = params[:offense]
   @defense = params[:defense]
  end

lizardon = Pokemon.new(name: "リザードン", hp: 78, offense: 84, defense: 78)

puts lizardon.name
puts lizardon.hp
puts lizardon.offense
puts lizardon.defense

lizardon.hp -= 30

puts "#{lizardon.name}はダメージを受けた! 残りHPは#{lizardon.hp}だ"

end

8. アクセスメソッド(attr_accessor)

いよいよ最後です。attr_readerattr_writerを同時に定義できるメソッドがあるのです。それがattr_accessorです。こちらを使えば、attr_readerとattr_writerの記述を1行で表すことができます。

class Pokemon

  attr_reader :name, :hp, :offense, :defense
# セッターとゲッターを一括定義
  attr_accessor :hp

  def initialize(**params)
   @name = params[:name]
   @hp = params[:hp]
   @offense = params[:offense]
   @defense = params[:defense]
  end

lizardon = Pokemon.new(name: "リザードン", hp: 78, offense: 84, defense: 78)

puts lizardon.name
puts lizardon.hp
puts lizardon.offense
puts lizardon.defense

lizardon.hp -= 30

puts "#{lizardon.name}はダメージを受けた! 残りHPは#{lizardon.hp}だ"

end

出力結果

リザードン
78
84
78
リザードンはダメージを受けた! 残りHP48

まとめ

initializeは初期化
attr_readerはゲッター
attr_witerはセッター
attr_accessorはセッターとゲッターの両方の機能

という感じで使われています!

以上です。最後まで読んでいただきありがとうございました。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3