rubyのゲッターとセッターについて解説した記事のアイキャッチ画像。

【Ruby】ゲッターとセッターを理解する

プログラミング学習初めて2ヶ月の初学者です。

学習したことをアウトプットします。

この記事でわかること

  • ゲッターとセッターとは?
  • なぜ必要なのか?
  • Rubyでどう定義するのか?
  • attr_reader / attr_writer / attr_accessor とは何か?

前提:クラス・インスタンス・インスタンス変数について

ゲッターとセッターの話の前に、クラスとインスタンス、インスタンス変数について復習します。

Rubyでは、

  • クラス:設計図
  • インスタンス:設計図からつくられた実態
  • インスタンス変数:各インスタンスが「自分だけがもっているデータ」

を表します。

class Book
  def initialize(title)
    @title = title
  end
end

book = Book.new("ハリーポッター")

ここで起きていることは、

  • Bookという「本の設計図」をつくる
  • Book.new("ハリーポッター")で、実際の本(インスタンス)を一冊つくる
  • initialize(title)メソッドが呼ばれて、@titleに"ハリーポッター"を入れる

という流れ。

  • Book.new(...)新しい本をつくって
  • initialize(...)つくるときに最初の値をセットする

というようなイメージです。

new ,initializeメソッドについてよくわからない方は下記記事で紹介しています。

rubyのnew、initializeメソッドについて学んだことをアウトプットするアイキャッチ画像。
【Ruby】newメソッドとinitializeメソッドを理解する

プログラミング学習初めて2ヶ月ほど経ちました。 インプットばかりでアウトプットがおろそかになっているので、自分の学習の理解を深めるためにも学んだことを共有したいと思います。 今回は、newメソッドとi ...

続きを見る

ゲッター/セッターとは?

Rubyでは、オブジェクトが持っている値(インスタンス変数@xxx)は、外部から直接読み書きできないように守られています。

そこで必要になるのが、

  • 値を読むためのメソッド:ゲッター
  • 値を変更するためのメソッド:セッター

データ保護のための仕組みです。(カプセル化)

なぜ必要なのか?

ゲッター・セッターがなぜ必要なのかをみていきます。

例として、本のタイトルを扱う Book クラスを考えます。

class Book
  def initialize(title)
    @title = title
  end
end

book = Book.new("ハリーポッター")
book.title
# => NoMethodError(直接参照できない)

book.titleと書くとエラーになります。

ここで重要なのは、Rubyでは「外からインスタンス変数(@title)に直接アクセスする文法はない

ということです。

Rubyのオブジェクトに対してできるのは、メソッドを呼び出すことだけ。

  • book.titleは「bookというオブジェクトに対して、titleというメソッドを呼ぼうとしている」
  • だが、Bookクラスにはdef title... endが定義されていないためNoMethodErrorになります。

@titleを返してくれるメソッドが定義されていないからなんですね。

そこで必要なのが、ゲッター/セッターになります。

ゲッターを定義すると読み出せる

@titleを読むためのメソッドを自分で用意するのがゲッターです。

class Book
  def initialize(title)
    @title = title
  end

  def title  # ← ゲッター
    @title
  end
end

book = Book.new("ハリーポッター")
book.title # => "ハリーポッター"

ここで行なっていることは、

  • book.titleを呼ぶ
  • RubyがBookクラスの中からdef titleを探す
  • 見つかったため、そのメソッドの中身@titleを返す
  • 結果、"ハリーポッター"が返る

という流れです。

外から@titleを直接参照するのではなく、「@titleを返してくれるメソッド(ゲッター)を通して参照している」というイメージ

セッターを定義すると変更できる

@titleをあとから変更したい場合にセッターを使います。

class Book
  def initialize(title)
    @title = title
  end

  def title=(new_title)  # ← セッター
    @title = new_title
  end
end

book = Book.new("ハリーポッター")
book.title = "賢者の石"

ここでのポイントは、

メソッド名がtitle = になっている点。

Rubyでは、book.title = "賢者の石"という書き方をすると、内部的にはbook.title = ("賢者の石")というメソッド呼び出しになるルールがあります。

この「= を含んだメソッド名」がセッターです。

つまり、

book.title ="賢者の石"はセッターによって@titleが変更された結果ということ。

attr_reader / attr_writer / attr_accessorとは?

Ruby では、ゲッター・セッターは、下記の便利メソッドを使うことで1行で自動生成できます。

メソッド役割自動で定義されるもの
attr_reader参照のみゲッター
attr_writer更新のみセッター
attr_accessor参照 & 更新ゲッター + セッター

attr_reader

attr_readerの使い方の例です。

class Book
  attr_reader :title

  def initialize(title)
    @title = title
  end
end

book = Book.new("ハリーポッター")
book.title # => "ハリーポッター"
book.title = "" # => NoMethodError(セッターがないので書き換え不可)

attr_reader :title は、裏側でこんなメソッドを定義してくれています。

def title
  @title
def

attr_reader

attr_wirterの使い方の例です。

class Book
  attr_writer :title

  def initialize(title)
    @title = title
  end
end

book = Book.new("ハリーポッター")
book.title = "賢者の石" # => OK
book.title # => NoMethodError(ゲッターがない)

attr_accessor

attr_accessorの使い方の例です。

class Book
  attr_accessor :title

  def initialize(title)
    @title = title
  end
end

book = Book.new("ハリーポッター")
book.title          # => "ハリーポッター"
book.title = "賢者の石"
book.title          # => "賢者の石"

attr_accessorr :title は、内部で下記2つを自動で定義してくれています。

def title
  @title
def

def title=(new_title)
  @title = new_title
end

ゲッター/セッター まとめ

Rubyのオブジェクトは外部から直接触れられないためメソッドを使う必要があります。

ゲッター/セッター

  • インスタンス変数(@title)を外から使うにはゲッター/セッターを使用
  • 値を読むためのメソッド:ゲッター
  • 値を変更するためのメソッド:セッター
  • 毎回書くのは大変なので、attr_reader / attr_writer / attr_accessor が用意されている

という感じに理解しました。

ここまで読んでいただきありがとうございます。

-Ruby
-, , ,

Translate »