【Ruby】レッスン5-03:アクセスメソッド(getter・setter)の使い方を理解しよう

50110130

一つ前のページではイニシャライザについて学習しました。

今回は アクセスメソッド について見ていきましょう。

Lesson1:基礎文法編
Lesson2:制御構造編
Lesson3:メソッド編
Lesson4:コレクション編
Lesson5:オブジェクト指向編

 ・Lesson5-1:クラスの基本を理解しよう
 ・Lesson5-2:イニシャライザを理解しよう
 ・Lesson5-3:アクセスメソッドを理解しよう ◁今回はココ
 ・Lesson5-4:クラス変数とクラスメソッドを理解しよう
 ・Lesson5-5:privateメソッドを理解しよう
 ・Lesson5-6:正規表現を理解しよう
 ・Lesson5-7:クラスの継承を理解しよう
 ・Lesson5-8:ファイル操作を理解しよう
 ・Lesson5-9:オーバーライドを理解しよう
 ・Lesson5-10:モジュールを使ってみよう
 ・Lesson5-11:ミックスインを使ってみよう
 ・確認問題5-☆1:モンスター捕獲ゲームを作ろう
 ・確認問題5-☆2:モンスターとの戦闘ゲームを作ろう
 ・確認問題5-☆3:マルバツゲームを作ろう

<<前のページ

Rubyの記事一覧

次のページ>>

Rubyのアクセスメソッドを基礎から解説

Rubyでプログラムを作成する際、クラスの内部に定義される「インスタンス変数」というものがあります。

この変数はクラス内で使用されるデータを保持しますが、外部から直接アクセスすることはできません。

そのため外部からインスタンス変数を安全に操作する方法として「アクセスメソッド」を使います。アクセスメソッドには次の2つがあります。

  1. ゲッター: 変数の値を取得するメソッド
  2. セッター: 変数の値を変更するメソッド

Rubyではこれらのメソッドを自動的に作成する便利な機能attr_accessorも用意されています。

本記事ではこのアクセスメソッドについて具体例を交えながら分かりやすく解説していきます。

アクセスメソッドが必要な理由と背景

まずアクセスメソッドがなぜ重要なのかを説明します。

Rubyではインスタンス変数を定義する際に@をつけます。この変数はクラス内からは参照できますが、外部から直接参照することはできません。

直接アクセスできない例

class User
  def initialize(name)
    @name = name # インスタンス変数の定義
  end
end

user = User.new("Taro")
# クラスの外からインスタンス変数にアクセス
puts user.name # エラー: undefined method `name' for #<User:...>

このエラーはインスタンス変数@nameがクラス外から直接参照できないために発生しています。

外部から安全に変数へアクセスする方法として、ゲッターやセッターを使います。

ゲッター・セッターの動作と定義方法

ゲッターとセッターを手動で定義することで、インスタンス変数の値を取得したり設定したりすることができます。

ゲッターの定義

ゲッターはインスタンス変数の値を取得するためのメソッドです。

class User
  def initialize(name) # initializeメソッドは、新しいインスタンスが作成されるときに呼び出される
    @name = name       # 引数nameを受け取り、インスタンス変数@nameに代入する
  end

  # クラスの中にゲッターを定義
  def name # このnameメソッドを呼び出すことで、インスタンス変数@nameの値を取得できる
    @name  # nameメソッド(ゲッターメソッド)の戻り値
  end
end

# Userクラスの新しいインスタンスを作成
user = User.new("Taro") # "Taro"をインスタンス変数@nameに保存
puts user.name          # => "Taro"(ゲッターで値を取得)

セッターの定義

セッターはインスタンス変数の値を変更するためのメソッドです。

=を使うことで、見た目が変数への代入のようになります。

class User
  def initialize(name)
    @name = name
  end

  # クラスの中にセッターを定義
  def name=(value) # name=メソッドを呼び出すことで、インスタンス変数@nameの値を変更できる
    @name = value  # インスタンス変数@nameに新しい値を代入
  end
end

# Userクラスの新しいインスタンスを作成
user = User.new("Taro")
user.name = "Hanako" # インスタンス変数@nameに新しい値"Hanako"を設定

attr_accessorでコードを効率化する方法

Rubyではゲッターとセッターを一つずつ手動で書く必要はありません。

attr_accessorを使えばゲッターとセッターを一括で作成できます。

attr_accessorを使った例

class User
  # ゲッターとセッターを自動生成
  attr_accessor :name # nameメソッド(ゲッター)とname=メソッド(セッター)が自動的に定義される

  def initialize(name)
    @name = name
  end
end

user = User.new("Taro")
puts user.name       # 自動生成されたゲッターメソッドを使用して@nameの値を取得 => "Taro"
user.name = "Hanako" # 自動生成されたセッターメソッドを使用して@nameの値を変更
puts user.name       # => "Hanako"

attr_accessor :nameの一行でゲッターとセッターの機能が追加されます。

これによりコードが簡潔になり、可読性が向上します。

attr_writer・attr_readerの違いと使い分け

場合によってはゲッターだけ、またはセッターだけを定義したいことがあります。

そのような場合はattr_reader(ゲッターのみ)やattr_writer(セッターのみ)を使用します。

attr_readerの例

ゲッターのみを定義する場合の例です。

class User
  attr_reader :name # ゲッターのみ定義

  def initialize(name)
    @name = name
  end
end

user = User.new("Taro")
puts user.name  # => "Taro"
# user.name = "Hanako" # エラー(セッターが定義されていないため)

attr_writerの例

セッターのみを定義する場合の例です。

class User
  attr_writer :name # セッターのみ定義

  def initialize(name)
    @name = name
  end
end

user = User.new("Taro")
user.name = "Hanako"
# puts user.name # エラー(ゲッターが定義されていないため)

アクセス制御を活用した応用例

アクセスメソッドを使うことでデータに対する制約を追加することもできます。

以下の例では、年齢が0以上の場合のみ値を変更するセッターを作成しています。

class User
  attr_reader :name
  attr_accessor :age

  def initialize(name, age)
    @name = name
    @age = age
  end

  # 年齢を制限するセッター
  def age=(value)
    if value >= 0
      @age = value
    else
      puts "無効な年齢です"
    end
  end
end

user = User.new("Taro", 20)
puts user.name  # => "Taro"
puts user.age   # => 20
user.age = -5   # => "無効な年齢です"
puts user.age   # => 20(変更されない)

このようにセッターをカスタマイズすることで、不正なデータの入力を防ぐことができます。

アクセスメソッドの学習まとめ

アクセスメソッドはオブジェクト指向プログラミングにおいて重要な役割を果たします。

ゲッターとセッターを使用することで、データの安全性を保ちながら操作が可能になります。

attr_accessorをはじめとするRubyの便利な機能を活用することで、簡潔で効率的なコードを書くことができます。

ぜひ自分のコードでも積極的に使ってみてください!

練習問題|アクセスメソッドを使ってRubyの理解を深めよう

アクセスメソッドをしっかりと身に着けるため、練習問題に挑戦しましょう。

Rubyでアクセスメソッドを使う課題に挑戦

attr_accessorを使ったゲッターとセッターの自動生成について学びましょう。

名前と年齢を管理するPersonクラスを作成し、以下のような機能を持つプログラムを完成させてください。

プログラムの最後にはクラスのメソッドを使って、特定の動作を実行してみましょう。

以下の要件に従ってコードを完成させてください。

  1. Personクラスを定義すること。
  2. attr_accessorを使用してnameageという2つのインスタンス変数のゲッターとセッターを自動生成すること。
  3. イニシャライザ(initializeメソッド)を作成し、nameageを初期化できるようにすること。
  4. have_birthdayというメソッドを作成し、年齢を1歳増やし、「〇〇さん、お誕生日おめでとうございます!」というメッセージを出力すること。
  5. Personクラスのインスタンスを生成し、以下の操作を行うこと:
    • 名前と年齢を取得し、画面に出力する。
    • 名前を変更し、変更後の名前を画面に出力する。
    • have_birthdayメソッドを呼び出し、結果を画面に出力する。

ただし、以下のような実行結果となること。

名前: たかし
年齢: 20歳
新しい名前: ゆかり
ゆかりさん、お誕生日おめでとうございます!年齢は21歳になりました。

【ヒント】自力で解くのが難しい人へ

1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。

Q
ヒント1【コードの構成を見る】

正解のコードは上から順に以下のような構成となっています。
(※下記の□はコード内のインデントを表しています)

1:クラスPersonを定義
  □ attr_accessorを使用して、nameとageのゲッターとセッターを自動生成
  □ initializeメソッドを定義
  □ □ 引数nameをインスタンス変数@nameに代入
  □ □ 引数ageをインスタンス変数@ageに代入
  □ have_birthdayメソッドを定義
  □ □ インスタンス変数@ageに1を加算
  □ □ f文字列を使って「〇〇さん、お誕生日おめでとうございます!」を出力

2:Personクラスのインスタンスを生成し、変数personに代入
3:personオブジェクトのname属性を出力
4:personオブジェクトのage属性を出力
5:personオブジェクトのname属性に”ゆかり”を代入
6:変更後のname属性を出力
7:have_birthdayメソッドを呼び出し、その結果を出力

Q
ヒント2【穴埋め問題にする】

以下のコードをコピーし、コメントに従ってコードを完成させて下さい。

# クラスPersonを定義します
class Person
  # attr_accessorを使用して、ゲッターとセッターを自動生成
=begin
  【穴埋め問題1】
  ここにattr_accessorを使用して、nameとageのゲッターとセッターを自動生成するコードを書いてください。
=end

  # イニシャライザを定義して、初期化時に値を設定できるようにする
=begin
  【穴埋め問題2】
  ここにinitializeメソッドを定義し、引数nameとageをインスタンス変数@nameと@ageにそれぞれ代入するコードを書いてください。
=end

  # 年齢を1歳増やすメソッド
  def have_birthday
=begin
    【穴埋め問題3】
    ここにインスタンス変数@ageに1を加算し、"〇〇さん、お誕生日おめでとうございます!"というメッセージを出力するコードを書いてください。
=end
  end
end

# Personクラスのインスタンスを作成
=begin
【穴埋め問題4】
ここでPersonクラスのインスタンスを作成し、変数personに代入するコードを書いてください。
=end

# ゲッターを使ってnameとageを出力
=begin
【穴埋め問題5】
ここでpersonオブジェクトのnameとageを取得して出力するコードを書いてください。
=end

# セッターを使ってnameを変更
=begin
【穴埋め問題6】
ここでpersonオブジェクトのname属性を変更し、変更後のnameを出力するコードを書いてください。
=end

# 年齢を1歳増やすメソッドを実行
=begin
【穴埋め問題7】
ここでpersonオブジェクトのhave_birthdayメソッドを呼び出して、その結果を出力するコードを書いてください。
=end

このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。

この問題の解答例と解説

この問題の正解コードとその解説は以下の通りです。

クリックして開いて確認してください。

Q
正解コード
# クラスPersonを定義します
class Person
  # attr_accessorを使用して、ゲッターとセッターを自動生成
  attr_accessor :name, :age

  # イニシャライザを定義して、初期化時に値を設定できるようにする
  def initialize(name, age)
    @name = name # インスタンス変数nameに値を設定
    @age = age   # インスタンス変数ageに値を設定
  end

  # 年齢を1歳増やすメソッド
  def have_birthday
    @age += 1
    puts "#{@name}さん、お誕生日おめでとうございます!年齢は#{@age}歳になりました。"
  end
end

# Personクラスのインスタンスを作成
person = Person.new("たかし", 20)

# ゲッターを使ってnameとageを出力
puts "名前: #{person.name}"
puts "年齢: #{person.age}歳"

# セッターを使ってnameを変更
person.name = "ゆかり"
puts "新しい名前: #{person.name}"

# 年齢を1歳増やすメソッドを実行
person.have_birthday
Q
正解コードの解説

コードをブロックごとに分割して解説します。

クラスの定義とアクセスメソッド

class Person
  attr_accessor :name, :age
  1. class Person
    クラスPersonを定義しています。Personクラスは名前と年齢を持つ人を表現します。
  2. attr_accessor
    attr_accessorは指定したインスタンス変数に対応するゲッター(取得メソッド)セッター(設定メソッド)を自動生成するRubyの便利な文法です。
    このコードでは、nameageの両方のインスタンス変数に対してゲッターとセッターが生成されます。

例えばperson.nameで名前を取得し、person.name = "新しい名前"で名前を変更することができます。

イニシャライザの定義

  def initialize(name, age)
    @name = name
    @age = age
  end

イニシャライザはPersonクラスのインスタンスが作成されるときに実行されます。

このようにして、オブジェクト生成時に名前と年齢を指定できるようになります。

引数nameageを受け取り、それぞれインスタンス変数@name@ageに代入しています。

メソッドの定義

  def have_birthday
    @age += 1
    puts "#{@name}さん、お誕生日おめでとうございます!年齢は#{@age}歳になりました。"
  end

このメソッドは年齢を1歳増やし、お祝いメッセージを表示します。

  • putsで動的に年齢を組み込んだメッセージを出力します。
  • @age += 1で、現在の年齢を1歳増やしています。

インスタンスの作成と操作

person = Person.new("たかし", 20)
puts "名前: #{person.name}"
puts "年齢: #{person.age}歳"
  • インスタンスの作成
    Person.new("たかし", 20)Personクラスのインスタンスを生成し、変数personに代入しています。ここで名前を「たかし」、年齢を20歳として設定しています。
  • ゲッターの使用
    person.nameで名前を取得しperson.ageで年齢を取得しています。それぞれを出力しています。

セッターの使用

person.name = "ゆかり"
puts "新しい名前: #{person.name}"
  • セッターの使用
    person.name = "ゆかり"で名前を「ゆかり」に変更しています。このコードはattr_accessorによって自動生成されたセッターを利用しています。
  • 変更後の名前の取得
    puts "新しい名前: #{person.name}"で変更後の名前を確認しています。

メソッドの呼び出し

person.have_birthday

person.have_birthdayで誕生日を祝うメッセージを表示し、年齢が1歳増えます。

まとめ

このコードではの「アクセスメソッド(attr_accessor)」を使うことで、クラスのインスタンス変数を簡単に操作する方法を学べます。

これによりコードの簡潔さと可読性が向上します。

クラスの作成やメソッドを通じたインスタンスの操作に慣れることは、オブジェクト指向プログラミングを理解する第一歩です。

今回のコードを基に、他のクラスや属性を追加して試してみましょう!

もっと分かりやすいサイトにするために

この記事を読んで「ここが分かりにくかった」「ここが難しかった」等の意見を募集しています。

世界一わかりやすいRuby学習サイトにするため、ぜひ 問い合わせフォーム からご意見下さい。

<<前のページ

Rubyの記事一覧

次のページ>>

FAQ|Rubyのアクセスメソッドとattr_accessorの使い方

Q
Q1. Rubyでゲッターとセッターを明示的に書く必要はありますか?

基本的にはattr_accessorを使うことでゲッターとセッターを自動生成できますが、バリデーションや条件分岐など特別な処理が必要な場合は、メソッドを明示的に定義するのが適切です。

Q
Q2. attr_readerとattr_writerの違いは何ですか?

attr_readerはゲッターのみ、attr_writerはセッターのみを自動定義する構文です。たとえば、読み取り専用にしたいインスタンス変数にはattr_readerを使うことで、安全な設計を実現できます。

Q
Q3. セッターを使って値に制限を設けるにはどうすればいいですか?

セッターメソッドを手動で定義し、条件文を使うことで値に制限を加えられます。例えば、負の年齢を拒否したい場合はif文を使って条件に合わない値の代入を防ぐことが可能です。

記事URLをコピーしました