今回はクラスの重要な機能、継承について。 | |
けいしょう? | |
継承っていうのは、あるクラスのメンバ変数・メソッド・メンバプロパティを全部引き継いで新しいクラスを作ることだよ。 | |
えっと、具体的にはどういうことなの? | |
じゃあ、実際に継承してみるね。 |
<継承の例:Input クラス(スーパークラス)の定義>
これが継承元になる Input クラスの定義ね。 | |
継承元って? | |
継承元になる Input クラスを継承して新しいクラスを作ると、そのクラスは Input クラスのメンバ、 つまり prevInput メンバ変数と getInput メソッド、それから previous プロパティが定義しなくても使えるようになるんだ。 | |
へぇ…そうなんだ。 | |
で、継承元のクラスのことをスーパークラスって呼ぶの。 あと「基底クラス」「基本クラス」「親クラス」って言ったりもするんだけど、ここでは「スーパークラス」って呼ぶことにするね。 |
|
うん、わかった。スーパークラスね。 | |
じゃあ、getInput メソッドの動作は解る? | |
えっと、まず inputString メソッドを呼び出してるね。 | |
うん。 | |
それで、inputString メソッドの戻り値が void だったら何もせずに false を返して、 void じゃなかったら、その戻り値を prevInput っていうメンバ変数に代入して true を返すんだよね。 | |
ん、そう。 つまり、OK ボタンが押されたら真を返して、キャンセルボタンが押されたら偽を返すってことだね。 あと、getInput メソッドは引数を省略できるようになってるよ。 |
|
getInput メソッドの引数はそのまま inputString メソッドに渡されてるから、 第1引数が入力ウィンドウのタイトルに表示される文字列で、省略すると空文字列になるんだよね。 | |
うんうん。 | |
第2引数は文字を入力するボックスの上に表示される文字列で、省略すると "値を入力してください。" っていう文字列になるよね。 | |
そうそう。 じゃあ第3引数は? |
|
第3引数のデフォルト値って、メンバ変数の prevInput なの? | |
そ。デフォルト値にはメンバ変数も指定できるからね。 prevInput は前回入力された内容を記憶しておく変数だから… |
|
第3引数を省略すると、前回入力された文字列が最初から表示されてるってこと? | |
そゆこと。 ちなみに初めて入力ウィンドウを表示するときは、第3引数を省略するとデフォルト値が空文字列になるから、何も入力されてない状態になるよ。 |
|
なるほどね。 | |
あと previous プロパティも見とこっか。 | |
previous プロパティはゲッターしかないから読み出し専用で、 prevInput の値をそのまま返してるね。 | |
ん、そう。 つまり previous プロパティは前回入力された文字列を取得できるプロパティ。 |
|
うん。 これで Input クラスは解ったよ。 |
|
じゃあ、今度は Input クラスを継承して新しいクラスを作ってみるね。 |
<継承の例:Input クラスを継承して作った Calculator2 クラス>
これって前回の電卓クラス? | |
機能的には、入力ウィンドウに前回入力した式が表示されること以外 Calculator クラスと同じだね。 でも Calculator2 クラスは Input クラスを継承して作ってるから、中身は違ってるよ。 |
|
確かに calculate メソッドの中身が前と違ってるね。 | |
うん。スーパークラスのメソッドとメンバ変数を使ってるからね。 で、継承の仕方なんだけど、extends っていうキーワードを使うんだ。 |
|
それって、クラス名の後に書いてある『extends Input』のこと? | |
うん、『class Calculator2 extends Input』っていうのは、
『Input クラスを継承して Calculator2 クラスを作るよ』って意味。 継承する場合は、こんなふうにクラスを定義するんだ。 |
<継承を行う場合のクラス定義>
継承先のクラスはサブクラスって言うの。 他にも「派生クラス」とか「子クラス」って呼ばれることもあるよ。 |
|
スーパークラスもそうだけど、こっちも色んな呼び方があるんだね。 | |
うん。継承元をスーパークラスって呼ぶ場合は、継承先はサブクラスって呼ぶのが普通だから、 ここではサブクラスって呼ぶことにするね。 | |
りょーかい。 | |
サブクラスを作る時に注意しなくちゃいけないのが、サブクラスのコンストラクタとデストラクタでは、 それぞれスーパークラスのコンストラクタとデストラクタを呼び出さなくちゃいけないってこと。 | |
それって『super.Calculate();』っていうのと『super.finalize();』っていうののこと? | |
うん、そう。 super っていうキーワードを使うと、スーパークラスのメンバ変数・メソッド・プロパティが使えるんだ。 |
|
じゃあ、『super.Calculate();』がスーパークラスのコンストラクタを呼び出してて、 『super.finalize();』がスーパークラスのデストラクタを呼び出してるってこと? | |
ん、そういうこと。 サブクラスを作る時にはこれを忘れないでね。 |
|
うん、わかった。 | |
んじゃ次は calculate 関数を見てみよっか。 | |
前回は最初に inputString メソッドを呼び出してたけど、今回は getInput メソッドを呼び出してるね。 | |
うん。さっきも言ったように、サブクラスからはスーパークラスのメソッドが使えるから、 getInput メソッドは Calculator2 クラスの中で定義しなくても使えるんだ。 | |
なるほどね〜。 あ、でもさっきスーパークラスのメソッドを使うときは super を使うって言ってたよね? getInput メソッドを呼び出してるところには super って書いてないよ? |
|
サブクラスに同じ名前のメソッドがない時は super は書かなくてもいいんだ。 | |
あ、そうなんだ。 | |
メンバ変数の prevInput も、 サブクラスに同じ名前のメンバ変数がないから super はつけてないでしょ。 | |
ほんとだ。 | |
後は、前回の expr が prevInput に変わってるだけだから、 これで calculate 関数は解ったよね? | |
うん、おっけーだよ。 | |
じゃあ最後は answer プロパティなんだけど、これはスーパークラスの要素を使ってないから説明しなくても大丈夫だよね。 | |
うん。answer プロパティは前と変わってないもんね。 | |
これで継承の事は大体解った? | |
うん、一応解ったんだけど… 何で Calculator2 クラスを作るのにわざわざ Input クラスを継承するの? Input クラスに電卓の機能を追加して作ればいいと思うんだけど… |
|
あー、それはこういう時のためだよ。 |
<もう一つのサブクラス:Time クラス>
これって、今から何分後かを表示するあれだよね? | |
そう、それ。前に作ったのよりは単純にしてるけどね。 こんなふうに Input クラスを継承して別のクラスも作れるんだ。 |
|
そっか。これも入力ウィンドウ表示するもんね。 | |
Input クラスに機能を追加して Calculator2 クラスを作るんだったら、 Time クラスも同じように Input クラスに機能を追加して作らなくちゃいけないから、 Input クラスの部分を2回書かなくちゃいけなくなるでしょ。 | |
あ、確かにそうだよね。 | |
Input クラスは単純だから2回書いてもそんなに変わんないかもしれないけど、 もっと複雑なクラスだったら何回も同じことを書くのは無駄でしょ。 | |
だから同じ部分はクラスにして共有するってこと? | |
うん、そういうこと。 | |
なるほどね〜、だから継承するんだね。 | |
継承を上手く使ったクラスが作れると効率的なスクリプトが書けるし、 KAG 用のプラグインとか作る時にも継承を使うから、継承は頑張ってマスターしてね。 | |
う〜ん、でもちょっと難しそう… | |
まぁ、色々スクリプトを書いてれば慣れるよ、きっと。 | |
そうかなぁ…? | |
それに、これから先も継承は結構使うしね。 | |
わかった、がんばるね! | |
うん。 じゃあ、今回はここまで。次回からはしばらく継承関係をやっていくね。 それじゃ、また次回! |