オブジェクト指向でテレビを作る
さて、以前にTVクラスを作成しましたが、ある時、一部のTVユーザから、私が作ったテレビに文字放送の機能を付けて欲しいという案が出たとします。しかし、私が作るテレビ全てに文字放送の機能が必要なわけではありません。明らかに、今のTVクラスに文字放送のための機能を加えることはやりすぎです。テレビのユーザ全てが文字放送を必要としているわけではないからです。このようなとき、オブジェクト指向では、どのようにするのでしょうか?
オブジェクト指向では、継承という方法で、これに賢い解決策を与えています。例えば、TVクラスの機能を継承したMoji_TVクラスは、次のようになります。
class Moji_TV extends TV { //Moji_TVクラスはTVクラスの機能を継承する // 文字放送の中身 } |
そして、この文字放送テレビクラスは、ユーザからは今までのTVクラスと同じように使えます。例えば、次のようにです。
public static void main(String args[]) { Moji_TV myTV = new Moji_TV(); // これが私の文字放送テレビです! myTV.Channel(7); // 私のテレビのチャンネルを7に合わせる myTV.Volume (10); // 私のテレビのボリュームを10に合わせる } |
この時、Moji_TVクラス内で、ChannelやVolumeを宣言して実装しなくても、文字放送テレビクラスのユーザからChannelやVolumeメソッドを呼び出せることがミソです。文字放送テレビクラスがすべきことは、新しく文字放送のための機能を実装するだけでよいのです。チャンネル変更やボリューム変更のためのコードはTVクラスによってすでに実装されていますので、それのためのプログラムはもう必要がありません。
では、この文字放送クラスに、新しく文字放送のためのメソッドを実装してみましょう。ここでは、テレビを通常のテレビモードから文字放送モードに変更するsetMojiModeを実装します。テレビのリモコンでいうなら、「文字放送」ボタンです。オン、オフで(true, false)でテレビのモードを変更します。
class Moji_TV extends TV { //Moji_TVクラスはTVクラスの機能を継承する // 文字放送の中身 private boolean m_bMoji=false; // 文字放送モード (最初は通常モード) // テレビモードを変更する:true=文字放送、false=通常モード public void setMojiMode (boolean bMoji) { m_bMoji = bMoji; } } |
この文字放送テレビクラスのユーザは、次のようにして文字放送をオン、オフすることができます。
public static void main(String args[]) { Moji_TV myTV = new Moji_TV(); // これが私の文字放送テレビです! myTV.Channel(7); // 私のテレビのチャンネルを7に合わせる myTV.Volume (10); // 私のテレビのボリュームを10に合わせる myTV.setMojiMode (true); // 文字放送モードに変更します } |
・・・いかがでしょうか?しつこいようですが、Moji_TVクラスでは実際にはsetMojiModeメソッドしか実装していないのに、Moji_TVクラスを利用するユーザからはChannelやVolumeなどのTVクラスのメソッドが呼び出せている、という点が重要なのです。また、新しく追加した、setMojiModeメソッドもChannelメソッドなどと同じように呼び出せている点にも注意。
さて、話はまだまだ続きます。文字放送モードをオン、オフするコードを書き終えたら、今度は文字放送のチャンネルを変更するメソッドを書く必要があります。もちろん、文字放送のチャンネル数は、通常の放送のチャンネル数と関係ないですし、両者はお互いに干渉するものではないことは明白です。そこで、文字放送のチャンネルを変更するメソッドを書いてみることにしましょう。
しかし、ここで疑問が湧いてきます。今私たちは、文字放送用のChannelメソッドを必要としているわけですが、すでに上位クラスのTVクラスにはChannelというメソッドがあり、実際にユーザはそれを使っています。「メソッドのオーバーロード」という方法を使えたら良いのですが、今回はTVクラスのChannelメソッドと全く同じ引数を持ったメソッドを再定義したいわけです。では、どうするのでしょうか?オブジェクト指向プログラミングでは、「スーパークラスのメソッドのオーバーライド」という方法を使います。要するに、TVクラスのChannelメソッドをMoji_TVクラス用に上書きしてしまうわけです。これは都合がいいですね。
では、Moji_TVクラスに、新しく文字放送チャンネルのためのChannelメソッドを書いてみましょう。
class Moji_TV extends TV { //Moji_TVクラスはTVクラスの機能を継承する // 文字放送の中身 private boolean m_bMoji=false; // 文字放送モード (最初は通常モード) private int m_nMojiChannel; //文字放送チャンネル final int MAX_MOJICHANNEL=70; //最大文字放送チャンネル数 final int MIN_MOJICHANNEL=1; //最少文字放送チャンネル数 // テレビモードを変更する:true=文字放送、false=通常モード public void setMojiMode (boolean bMoji) { m_bMoji = bMoji; } // Channelメソッドの上書き public void Channel(int nNewChannel) { if (m_bMoji) { // 文字放送がオンだった場合 //チャンネルレンジのチェック if (nNewChannel > MIN_MOJICHANNEL && nNewChannel < MAX_MOJICHANNEL) { m_nMojiChannel = nNewChannel;//文字放送用チャンネルに変更 } } else { super.Channel(nNewChannel);//TVクラスのChannelメソッドの呼び出し } } } |
上記のコードでは、TVクラスのChannelメソッドを上書きし、文字放送モードがオンの時にチャンネルが変更された時には、文字放送のチャンネルを変更し、それ以外の時(文字放送がオフの時)には、TVクラス(スーパークラスといいます)のChannelメソッドを呼び出しています。
Moji_TVクラスのユーザからの呼び出しは、次のようになります。
public static void main(String args[]) { Moji_TV myTV = new Moji_TV(); // これが私の文字放送テレビです! myTV.Channel(7); // 私のテレビのチャンネルを7に合わせる myTV.Volume (10); // 私のテレビのボリュームを10に合わせる myTV.setMojiMode (true); // 文字放送モードに変更します myTV.Channel(7); // 文字放送の7チャンネルに合わせる (Moji_TVクラスのメソッド) myTV.setMojiMode (false); // 通常モードに変更 myTV.Channel(6); //民放を見る (TVクラスのメソッド) } |
どうでしょうか?同じChannelメソッドの呼び出しでも、その時の文字放送モードによって、Moji_TVクラスのメソッドとTVクラスのメソッドが使い分けられているのが分かるでしょうか?手続き型プログラムの視点からすると、まるで魔法のようだと思いませんか?
上位クラスのメソッドをそのまま使えたり、自分の都合の良いように変更してしまったり、実に自由度が高く、しかも大事な情報(最大チャンネル数など)はユーザには隠されてるために、非常に堅牢なプログラムを書くことが出来ました。