7-5-3 Rubyの強力な言語仕様の側面を理解しよう
インスタンスのデータに値を代入する
インスタンス内で共通で使うことができるデータは、インスタンス変数です。
外部からインスタンス変数に値を代入する為には、代入用のメソッドを別途クラスに定義する必要があります。
代入用のメソッドを定義するには、def メソッド=(引数)
と記述します。
体験で確認したエラーメッセージからも読み取れるように、代入用のメソッド名はイコール(=
)までを含めたものとなります。
よって、イコールがない場合のメソッド名とは別のメソッドとして認識されます。
前ページ「7-5-2 健康診断を行うクラスをアクセサメソッドを使って実装しよう」の例では、MedicalExaminator
クラスのheight=
メソッドとheight
メソッドとは別物ということになります。
アクセサメソッド
アクセサメソッドは、attr_writer
、attr_reader
、attr_accessor
の後の半角スペースの後に、インスタンス変数の@抜きの文字列をシンボルで記述することで使用できます。
attr_writer
attr_writer
は、シンボルで記述した名前のメソッドでインスタンス変数に代入する処理を同時に行います。
前ページ「7-5-2 健康診断を行うクラスをアクセサメソッドを使って実装しよう」の例で言うと、attr_writer :height
と定義すれば、インスタンス.height = 代入したい値
のように使うことができます。
この式が評価されると、インスタンス変数@height
に値が代入されます。
attr_writer
を使ったプログラムは、以下のプログラムと同じ動作となります。
# attr_writerを使用した場合 class MedicalExaminator attr_writer :height end # attr_writerを使用しない場合 class MedicalExaminator def height=(height) @height = height end end
attr_reader
attr_reader
は、シンボルで記述した名前のメソッドでインスタンス変数の値を戻り値として返却します。
前ページ「7-5-2 健康診断を行うクラスをアクセサメソッドを使って実装しよう」の例で言うと、attr_reader :height
と定義すれば、インスタンス.height
のように使うことができます。
この式が評価されると、インスタンス変数@height
の現在の値を取り出すことができます。
attr_reader
を使ったプログラムは、以下のプログラムと同じ動作となります。
# attr_readerを使用した場合 class MedicalExaminator attr_reader :height end # attr_readerを使用しない場合 class MedicalExaminator def height @height end end
attr_accessor
attr_accessor
は、attr_writer
とattr_reader
の両方の定義を同時に行います。
インスタンス変数をメソッドのように使って代入したり参照したりすることを簡単に行えるようになります。
なお体験の例で確認した通り、複数定義したい場合は、アクセサメソッドの後にシンボルをカンマ区切りで記述します。
attr_accessor
を使ったプログラムは、以下のプログラムと同じ動作となります。
# attr_accessorを使用した場合 class MedicalExaminator attr_accessor :height end # attr_accessorを使用しない場合 class MedicalExaminator def height=(height) @height = height end def height @height end end
アクセサメソッドのまとめ
まとめると、アクセサメソッドには以下の3つの種類があります。
アクセサメソッドの種類 | 用途 |
---|---|
attr_writer |
外部からインスタンス変数へ書き込みのみ許可する。外部からの読み込みは許可しない。 |
attr_reader |
外部からインスタンス変数の読み込みのみ許可する。外部からの書き込みは許可しない。 |
attr_accessor |
外部からインスタンス変数の読み込み/書き込みの両方を許可する。 |
前ページ「7-5-2 健康診断を行うクラスをアクセサメソッドを使って実装しよう」の例で確認した通り、アクセサメソッドは、インスタンス変数を外部から操作する為に強力なサポートをしてくれます。
DSL
アクセサメソッドは、オブジェクト指向スクリプト言語としてのRubyの特徴を表しています。
このアクセサメソッドのように、attr_accessor :height
など、特定の宣言をすることで、普通にプログラムを記述するよりも単純化できる仕組みのことをDSL(Domain Specific Language:ドメイン固有言語)と呼びます。
Rubyにおけるアクセサメソッドは、DSLの中でも内部DSLと言われ、あるプログラムによって別のプログラムを記述する仕組みを提供してくれています。
このようなRubyの特徴は、メタプログラミングと呼ばれます。
メタプログラミングについての詳細は、入門者向けの解説範囲を超えているので解説は省略します。
しかし、「Rubyといえばメタプログラミング」と言っても言い過ぎではないほどRubyというプログラミング言語の特徴をよく表現しています。
メタプログラミングはRubyの面白い部分でもあるので、本サイトが物足りなくなった方は是非ご自身で調べてみてください。
スコープ(範囲)とは
クラスのpublicメソッドやprivateメソッドの違いは、インスタンスからアクセスできるか否かの違いでした。
言い換えると、アクセス可能な範囲がメソッドの種類によって異なるといえます。
アクセサメソッドの違いは、インスタンスから書き込めるか(write)、読み込めるか(read)、その両方かという違いでした。
言い換えると、インスタンス変数へのアクセス可能な範囲がアクセサメソッドの種類によって異なるといえます。
このように、アクセス可能性が異なる範囲のことをスコープと呼びます。
光が当たらない場所は暗くて見えないように、スコープによってできること/できないことが異なります。
まとめ
- アクセサメソッドを使って、インスタンス変数にクラス外部から間接的にアクセスできる
- アクセサメソッドは、内部DSLと呼ばれ、Rubyのメタプログラミングの特徴をよく表している