CSharp_object


※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

「カプセル化」「継承」「ポリモーフィズム」


見えるべきモノと隠すべきモノ

このサウンドロップは押す=「Push」とさっき設定した「Set」だけ外側から見えればいい。
しかしこのままではplaySoundも外側から見えて、インスタンス.playsound();とすれば実行されてしまいます。
あとはインスタンス.soundFileName = "hogehoge.wav"とせっかくSetで.wav以外をはじくように設定したのに・・・となってしまう。
そこで、アクセスしてほしくないデータにprivateを定義して外側から操作できないようにします。これが「カプセル化」というヤツですな。

using System;
using System.Media;

namespace SoundropNamespace{
 class Soundrop{
  private string soundFileName;
  private SoundPlayer player;
  public void Push(){
   playSound(soundFileName);
  }
  public void SetSoundName(string filename){
   soundFileName = filename;
  }
  //参考ページより引用。
  private void playSound(string filename){
   //再生されているときは止める
   if (player != null)player.Stop();
   //読み込む
   player = new System.Media.SoundPlayer(filename);
   //非同期再生する
   player.Play();
  }
  [STAThread]
  public static void Main(){
   Soundrop sd = new Soundrop();
   sd.SetSoundName("guil.wav");
   sd.Push();
  }
 }
}

アクセス修飾詞は主にこの3つを利用します。
  • private:クラスの外側からはアクセス不能
  • public:クラスの外側からでもアクセス可能
  • private:このクラスを継承したサブクラス*と、自身の内側からアクセス可能

サブクラスの説明は「リュウは8分の1で竜巻旋風脚を出す」の項目で説明します。
ここでSoundropはPushとSetSoundNameだけあればいいので、それ以外はprivateに設定します。
で、逆にその2つはpublicに設定します。ここで見えなくなったか次のようなソースを打って見ましょう。

nosource.

リュウは竜巻旋風脚を8回に1回は出す

リュウは8回に1回の割合で竜巻旋風脚が出るので、その処理を書き加えなければいけないので継承をして機能を書き換えてしまいましょう。継承とは・・・
class B : class A{}

と書くことで、classAで記述したコード(publicとprotected修飾詞が付いた関数)を今から定義するclassBですでに定義したということにできる機能です。
SoundropクラスにあったplaySound関数などはそのままRyuクラスでも利用したいので、さっきの項目ではprivateにしたものの、
playSound関数のprivateの記述をprotectedに変えておきます。
又、サウンドロップはPushするだけで竜巻か波動か勝手に決めます。
つまりPushの内容は書き換える必要があります。普通であれば、Pushの関数が二個以上記述されているのはおかしい話で、
Soundropの方のPush関数を弄ってしまうでしょう。しかし、継承後にRyuのPushを書き換える場合はoverride修飾詞を利用することによって、
元の関数の記述を変えないで関数を定義することができます。コードを書き換えないということは新たなバグの発生を防ぐことができます。
(コードの量は工夫しないと多くなってしまいそうですけど。)
以下踏まえた上でのコード。

こうするとRyu以外でもボタンを一定量溜めてからボタンを離すと「ドスコイ!」という本田だったりの実装も
継承してオーバーライドして書き換えればいいのでカナリ楽です。

サウンドロップホルダー

ポリモーフィズム(多態性)で、スーパークラスが等しいクラスのインスタンスは、
スーパークラスのインスタンスと同じメソッドを持つ。よってスーパークラスのインスタンスと同様に配列に格納し扱うことが可能。

インタフェース

ここでいろいろ気づいたと思うのですが、外側から見たオブジェクトは実は中身がスカスカでも、
setとpushがあればプログラムのコンパイルを通す事が可能ということに気づくでしょう。
つまり「外見」さえ確定してしまえば、コンパイルを通す事が可能ということです。
その外見を守ってプログラムを作る仕組みに、「インタフェース」があります。サウンドロップのインタフェースは次のようになります。

nosource.

さっきのリュウの継承でやったように、このインタフェースを継承します。
すると、そのクラスはpushとsoundFileName.setを定義しないとコンパイルを通す事ができなくなります。
つまりコンパイルが通ったということはそのクラスにインタフェースで定義されている pushとsoundFileName.setの関数が定義されているということになります。
こうやって一部未確定な部分があるけど、とりあえずはコンパイルが通るよ、完成部分は動かせるよ、という状態にすることが可能というわけです。
あとは分担作業したときに、このインタフェースを継承して・・・と伝えるだけで、カッチリと嵌め込みやすくなるというワケです。
では中身はどうであれ、外見が確定しているのでさうんどろっぷホルダーに入っている(であろう)サウンドロップを順番にプッシュするプログラムを組んでみましょう。