前記事「【Ruby入門】クラスとオブジェクト」では、概念的な話を集中的に解説しました。
なんとなくしっくりこないという方がおおいのではないでしょうか?
それもそのはずで、手を動かして結果を確認しないと理解は確実なものになりません。
ただし、もう少しクラスについて学ぶべきことがあります。
それが終われば、実際にコードを書いてみて確認します。
退屈かも知れませんが、もう少し解説をお読みください。
用語をもう少し正確に
今まで、ばく然と「変数」「メソッド」と呼んできました。
しかしこれでは抽象的すぎて、以降解説を進めることができません。
ここで用語をキッチリと整理しましょう!
クラス、インスタンス
クラスは「型」、それを実体化したのが「インスタンス」です。実体化する行為は「インスタンス化」です。
(言語や現場によっては、インスタンスはオブジェクトと呼ぶことがあります。オブジェクトの方がより広義です。)
クラス変数、インスタンス変数
クラスにある変数をクラス変数、インスタンスにある変数をインスタンス変数といいます。
インスタンス変数は、インスタンス化しないとアクセスできません。当たり前といえばそうですが。
インスタンスごとにもつ変数なので、インスタンス間でたがいに干渉しません。
インスタンス変数は、通常はアクセサ経由でアクセスします。
一方クラス変数は、インスタンス化せずとも利用可能です。
関連する定数(変化しない、変化しては困る値)や、インスタンス間で共有したい変数をクラス変数として定義します。
コンストラクタ
クラスからインスタンスを生成すると同時に呼ばれるメソッドをコンストラクタといいます。
主にインスタンス変数の初期化に使われます。
アクセス修飾子
メソッドを、他のプログラムにどこまで公開するかを制御することができます。
インスタンスにおいて、外からアクセスさせたくない局所的なメソッドもありますし、アクセサメソッドのように、外からアクセスできないとまったく意味がないメソッドもあります。
外からアクセスさせるかどうかは、メソッド名にアクセス修飾子と呼ばれるものをつけることにより可能となります。
言語によって異なりますが、たいがいはpubic(公開)、private(非公開、つまりインスタンス内だけで利用)、protected(言語によりいろいろ)があります。
クラスの王道的使い道、継承
クラスを使う最大のメリットともいえる継承を解説します。
クラスは、上下関係があります。
自クラスの変数やメソッドを継承し、子クラス(またはサブクラス)を作ることができます。
継承される親クラス(またはスーパークラス)の持ち物、つまり変数やメソッドすべてがそのまま引き継がれます。
継承の何がうれしいか
書籍管理システムにおいて、機能的な改修を行う場合を考えてみましょう。
改修の内容は「書かれている言語を追加する」とします。つまり日本語や英語、中国語といった言語を追加し、検索の機能向上をめざすという要件です。
しかし、言語が必要なシーンは限定的で、クラスに手を加えるほどではない場合はどうでしょうか?
ましてやクラスが1つしかないシステムなどありえず、たいがいのシステムは相当なクラス数になります。
そんな部分的な改修のために、既存のソースに大きく手を入れたくない・・・そうなるのが自然です。
そんなときに役立つのが継承です!
継承とは、親クラスのもつ性質(変数やメソッド)を引き継ぎ、新たなクラスを作ることでしたよね?
また、クラスを使うメリットはまだあります。
今は1つのシステム内部での継承でした。しかし、他人が作ったクラスを、あたかも自分のプログラムの部品として使えるというのも、クラスのメリットです。
あるいは、Webシステムなどでフレームワークを使う場合にもクラスは活用されます。
フレームワークが提供する機能はたいていクラスとして提供されているので、それを使って基本部分はクラスのもつパーツをそのまま、クラスを継承して自分のアプリ特有の部分だけコーディングということをします。
Rubyで有名なフレームワーク「Ruby on Rails」でも、さまざまな箇所でフレームワークのもつクラスを継承し、Webアプリを構築していきます。
オーバーライドとポリモフィズム
親クラスとサブクラスで、同じメソッド名を使ってもエラーになりません。
実はこの方法は、いたって普通に行われています。この方法を使うと、親クラスのメソッドの中身を書き換えることなく、別の仕様で上書きできるのです。
親クラスにあるメソッドと同じメソッド名をサブクラスに定義して、仕様を上書きすることをオーバーライドといいます。
そんなことをして何になるのかと思われるかもしれませんが、このオーバーライドを使って「あること」ができます。
例えば、こんなケースを想定しましょう。
現在の貸出可能数を算出する方法が、以下のパターンに分かれる場合です。
- 複数の系列図書館に分散している (子クラス1)
- 閲覧場所と倉庫に分散している (子クラス2)
- 次月号が出ないと貸出可能にならない (子クラス3)
これらがすべて同じメソッド名「貸出可能数取得」で宣言されているとしましょう。
呼び出す側としてはどうでしょうか?
呼び出す側は、メソッド名は1種類で済んでしまいます。つまり呼び出す側は上記3つの呼び出される側の完成を待たずに開発を進められるし、今後さらに算出する方法が増えても呼び出す側に影響はありません。
これを、ポリモフィズムといいます。
まとめ
今まで一切ソースコードを使わずにクラスとは何かを解説してきました。おぼろげながらも概念はつかめたのではないでしょうか?
Rubyに特有なことは解説から除外しました。よって、Ruby以外の言語を習得したい方にも有効な内容ばかりです。
最近の開発言語はオブジェクト指向言語が大半です。フレームワークを使った解説にも、クラスの理解は必須です。
要は、クラスから逃げては済まされないのです。
最初はとっつきにくいかもしれませんが、何度も読み返して、解説を読みながら図を追ってみたりして、がんばって理解してみてくださいね!