プログラミング学習初めて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メソッドを理解する
プログラミング学習初めて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
defattr_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のオブジェクトは外部から直接触れられないためメソッドを使う必要があります。
という感じに理解しました。
ここまで読んでいただきありがとうございます。