クラスの概念

と、そのうまみ

クラスってなんなんだ?

と、オブジェクト指向を学習し始めると思うわけです。

設計図みたいなもの、だとかよくわからない例えが出るし、インスタンス、継承、親……と用語も多い。

そこで具体的にしかしわかりやすく説明しよう、という趣旨なのだ

クラスはなんのために使う?

オブジェクト指向言語、と呼ばれるものはむしろこれがないと使えないようにしているから。(プロトタイプベースは除く)

それ以外でも考えることを減らすためにかなり便利。

クラスってどんなの?

設計図、というたとえ自体は間違ってない。

でもそこについて話すと初学者に優しくないので一旦クラスを使ってできたもの(これをインスタンスという)について議論する。

・カウンタの場合

カウンタってあるよね?わからない人はデジタルカウンターとか数取器で検索かければいいと思う。

これの機能は3つ。


ボタンを押す……数字を1増やす

数字をリセットする……数字を0にする

数字を表示する……内部の数字が外側から見れるようにしている


プログラミングでこれを作ってみよう。

まず内部の数字は整数型とかで作る。

private int num;

とか書いてみようか。

ここで大事なのがprivate。

privateの意味は、クラスの外部から参照(見たり書き換えたり)できない、ということである。

そこでたかしくんがこう質問するわけだ。

「あれ!? 外部から数字が書き換えられなかったらなんも数字変わらんやん!」

焦るな焦るな。ここでは"直接"書き換えられないだけで、あとでいい感じになるから。


次に、上に書いた3つの機能を作る。

public void Add(){

    num = num + 1;

}

public void Reset(){

    num = 0;

}

public int GetNum(){

    return num;

}

ここで大事なのがpublic。

publicの意味は、クラスの外部から参照(これは関数なので、呼び出し)できる、ということである。

そこでたかしくんがこう質問するわけだ。

「は!? numをpublicにしたら全部解決するやんけ!」

愚か者め。

publicにしたらnumの数字が外部からどんなふうにでも書き換えられてしまうではないか。

といってもよくわからないだろうから、以下に使い方の例を示す。

下のほうに、もし数字がpublicだったら、というのを書くからたかしくんはそれでも読んでおきなさい。

クラスの使い方

実際にクラスを使ってみよう。

Unityではクラスというと

class Kurasu : MonoBehaviour

などと書いていることが多いが、これは「MonoBehaviour」というクラスの性質を受け継いだクラスを作ります、以下追加内容など……

という意味になる。

だから今回はこのコロン以下を省略して書いていこう。

class Counter{

  private int num = 0;

  public void Add(){

    num = num + 1;

  }

  public void Reset(){

    num = 0;

  }

  public int GetNum(){

    return num;

  }

}

これでクラスができた。

そしてクラスは設計図、といっていたので実際に設計してみる。

Counter counter = new Counter();

Counter型のcounterという変数に、Counter型を作って入れる。

これでカウンターを作った。今手元にあるような感覚だ。

できたてホヤホヤのカウンターを眺めながらウキウキしていると、向こうのほうから人が歩いてきた。早速使ってみよう。

counter.Add();

counter.Add();

counter.Add();

人がいなくなった……

さて、と君はカウンターを見る。

Debug.Log(counter.GetNum());

おおっ、3と表示された。

よしよし、動いているぞと思いながらリセットする。

counter.Reset()

Debug.Log(counter.GetNum());

もちろん0と表示される。

ふと、魔が差して数字を999に書き換えようかと思った。

counter.num = 999;

//コンパイルエラー!

しかし、privateなのでアクセスできませんと言われてしまった。つまりはカウンターの容器に指をつっこむことはできなかったわけだ。

また別の日、カウンターを両手に持ちたくなった。右手で男子を、左手で女子を数えたら客の傾向が見えてくると思ったからだ。

Counter counter2 = new Counter();

できた。よっしゃ使うぞー。

(counterを配列にして複数持つこともできます)

もしpublic変数で作ろうと思ったら

たかしくんは手続き型言語に心酔していた。だからグローバル変数みたく数字を使おうと思ったのだ。

「publicにしたらnumだけで済んで楽じゃん」

class Counter{

  public int num;

}

Counter c = new Counter();

3人カウントしてカウンターを見ることにした。

c.num = c.num + 1;

c.num = c.num + 1;

c.num = c.num - 1;

Debug.Log(c.num);

1

あれ?

おっとっと、間違えて引き算をしてしまっていたみたいです。

そう言っている間に100人が来ました。

実行結果は……93。

どうやら加えて4回どこかを書き間違えたみたいです。

100行のどこかを。

たかしくんは発狂しました。


後任のひとしくんは卵パックの会社で働いています。

「えっ、何このカウンターの作り方」

100回押してから気づきます。

一度に10個くるので10づつ増やさなければなりませんが……

「addの中身を書き換えれば済むと思っていたら、100行分書き直さないといけないじゃないか!」

ひとしくんは発狂しました。


後任のふさおくんはなんとなくでカウンターを使うことにしました。

c.num = c.num + 1;

Debug.Log(c.num);

一度押して、表示。

そしたら、89と返ってきました。

どうやら発狂したひとしくんやたかしくんが書いたコードでいつの間にか書き換えられていたようです。

ふさおくんはどこでnumが書き換えられているのか、と持っている環境で検索をかけました。

該当……214件

ふさおくんはアマゾンの奥地へと向かいました。


後任の遮二無二破戒僧(しゃにむにはかいそう)くんはすべて書き直し、2つ目のカウンターを作ろうとしました。

class Counter{

  public int num;

  public int num2;

}

Counter c = new Counter();

Counter c2 = new Counter();

手違いでカウンターが4種類になり、すぐさま死亡しました。


100年後、たかしくんのカウンターは持ち主のいないまま砂漠に埋まっていました。この時代でカウンターは以下のように書かなければなりません。

c.num = c.num * 3 - 1;

100年のあいだにどうやら算数の理が変わり、

1,2,5,14,41...

と数字を数えるようになったみたいです。

ある女の子がこれを偶然見つけました。

しかし使い方がわかりません。なんせ3回押したら3という数字が出てきてしまうのですから。

「つまり……えーっと……3回押すには」

c.num = c.num * 3 - 1;

c.num = c.num * 3 - 1;

c.num = c.num * 3 - 1;

「え……こんな長いの何度も書かないといけないの?」

女の子は砂漠にその悲しき産物を投げ捨て、クラスを自分で設計し始めました。

~fin~

クラスのまとめ

クラスではprivateとかしてできることを制限することで、「してはいけないこと」をできないように作れる。

決まったことしかしないのであれば、かんたんに繰り返せる。

することを変えたいのなら設計図を書き換えればかんたんに一括変更できる。

いくらでも同じ機能をもつものを作れる。

→何をprivateにするのか、どのような変数・関数を作るのかをよく考えればすごく使いやすくなる。(デザインパターン)

ところで

Counter counter = new Counter();

とか書いてた。ここでのcounterという変数は何者なのか?

かんたんにいうと所在地をメモったみたいなもの。

クラスの持っている変数はどこにあるのか、関数はどこにあるのか、ということが書いてある。

つまりはcounter自体は場所一覧しか書いていない。

だから

counter2 = counter;

とか書くと、counterもcounter2も同じものを扱っていることになる。

この場所情報をどう扱うか、というのは利用すればいろいろ面白いことができる。たとえばカウンター製造マシン。

class Machine(){

  class Counter(){}

  Counter MakeCounter(int password){

    if(password==1234)

    {return new Counter();}

    else

    {return null;}

  }

}

入力したパスワードが1234だったらCounterが作られる、というわけだ。

まあこれはすごくしょうもない例なので、いろいろ知りたい人は「デザインパターン」で検索しよう。

まあ私が知ってるのはこんなところかな。

いかがでしたか?