2018年09月14日

師匠のJava道場~第13回・インターフェースについて学ぶのじゃっ!!

師匠T:さぁ、いよいよこの講座も最終回じゃ! 覚悟はよいか?

弟子D:はい! とても長い道のりでしたね。

師匠T:うむ。今回はいよいよその総決算。それによって、おぬしの運命も決まる。心するがよい!

弟子D:わかりました! それで今回は?

師匠T:うむ。今回はインターフェースなるものについて説明する。ではいくぞ!

▽ 師匠、インターフェースとはなんぞや? ▽

弟子D:師匠、さっそくですが、インターフェースとはなんぞや?

師匠T:うむ。これは、簡単に言ってしまえば、メインとなるクラスに実装されて、ある機能を付加するもののことじゃ。

弟子D:ふむふむ。

師匠T:このインターフェースは、次の三つに大別されるぞ。

・〇〇〇able系……『~することが可能であること』を表すインターフェース。ただし、Throwableは例外。
・〇〇〇Listener……あるイベントの発生を通知するためのインターフェース
・名詞系……抽象化クラスのようなインターフェース

師匠T:〇〇〇able系は、それを実装することにより、ある機能を使うことが可能になるものじゃ。例えば、runnableであれば、マルチスレッドが『可能』になる、というような感じじゃな。

弟子D:なるほど。次の『〇〇〇Listener』系は?

師匠T:うむ。例えばVBでは、ボタンを押したり、テキストボックスの内容を変更したりすると、イベントが発生するじゃろ? 前者ならClickイベント、後者ならTextChangedイベント、という具合にな。

弟子D:はい。

師匠T:これを実装すると、そのようなイベントがJavaプログラム実行時に発生した場合、それを受け取ることができるのじゃ。もちろん、そのときに実行するコードを書くこともできるぞ。

弟子D:なるほどっ。

師匠T:最後の名詞系については、ここでは省略しておく。知りたくば、Java関係の書籍やサイトを見るがよい。

弟子D:さては、説明するのがめんどく……

師匠T:はぁっ!!(飛び蹴り

▽ 実装する方法と作成する方法なのじゃ! ▽

師匠T:続いては実装する方法じゃが、これは簡単。クラス宣言の最後に、予約語implementsを使って、こう付け加えればいいだけじゃ。

--------------------
class 〇〇〇 implements △△△
--------------------

師匠T:例えば、Sisyoクラスにrunnableインターフェースを実装したければ、このように書く。

--------------------
class Sisyo implements runnable
--------------------

師匠T:そして、作成する方法じゃが、こちらも難しいことはない。classの代わりにinterfaceで宣言すればいいだけじゃ。例えば、DeshiAというインターフェースを作りたければ、こう書けばいいわけだな。

--------------------
interface DeshiA
--------------------

師匠T:このとき、インターフェースが持つメソッドは、抽象クラスの抽象メソッドのように、宣言部だけを書くこと。中身は書くでないぞ。

弟子D:あの師匠。インターフェースを継承することはできないのでしょうか?

師匠T:もちろんできるぞ。その場合は、クラスと同じように、extendsを使えばよい。

弟子D:なるほどっ。

師匠T:さて。実装のついて一つ注意じゃ。インターフェースを実装すると、それに付随するメソッドも自動的に追加されるが、その追加されたメソッドを一つも実装しなかった場合は、そのクラスは抽象クラスにしなければならないので気を付けることじゃ。

弟子D:はいっ。……ところで、抽象クラスってなんでしたっけ?

師匠T:……はぁっ!!(飛び蹴り

弟子D:うわあっ。

師匠T:おぬしの頭は、容量が1KBしかないのか。第10回の講座を読み返してこいっ!

弟子D:うぅ、すいません、師匠……。

▽ インターフェースと抽象クラスの、似ている点、違う点じゃ! ▽

師匠T:さて、このインターフェースと抽象クラスはいくつか、似ている点と違う点がある。ここではそれを説明していくぞ。

弟子D:はい、師匠!

師匠T:まず、インターフェースも抽象クラスも、newでインスタンスを作ることはできない。じゃが、参照型変数を作ることはできる。あらかじめ言っておくが、もし参照型変数のことがわからなければ、過去の記事を読むように。

弟子D:は、はい。して、そのほかには?

師匠T:うむ。インターフェースのメソッドも抽象クラスの抽象メソッドも、作るときはメソッド名だけを決める。つまり、そのメソッド内の処理は書かない、ということじゃな。

弟子D:なるほど。

師匠T:続いて違う点じゃが、一つ目。当然のことじゃが、抽象クラスはクラスじゃが、インターフェースはクラスではない。

弟子D:そういえば、抽象クラスはclassで宣言しますが、インターフェースはinterfaceですものね。

師匠T:うむ。そして二つ目。抽象クラスは、抽象メソッドではないメソッドも持つことはできるが、インターフェースは中身のないメソッドしか持つことはできないのじゃ。

弟子D:ふむふむ。

師匠T:そして最後。抽象クラスは、中身を変更できるフィールド(他の言語で言う変数)を持つことができるが、インターフェースはpublic static finalで宣言されるもの……つまり定数しか持つことはできぬのじゃ。

弟子D:なるほど。

▽ 師匠、インターフェースの利点とはなんぞや ▽

師匠T:では最後じゃ。ここでは、インターフェースの利点について語るとしようぞ。まず一つ目じゃが、インターフェース型の参照型変数では、それに対して、toStringメソッドやequalメソッドなどのObjectクラスで宣言されているメソッドを呼び出すことができる。

弟子D:ふむふむ。

師匠T:そして二つ目。以前言った通り、Javaでは多重継承をすることはできぬが、インターフェースをいくつも実装することはできる。これによって、疑似的に多重継承をすることができるのじゃ。

弟子D:なるほど、それは重要なポイントですね。それで次は?

師匠T:うむ。インターフェースを使って、多態性を実現することができる。共通のメソッドを持つインターフェースを、それぞれのクラスに実装する、という方法じゃな。

java1809-01.jpg

師匠T:この場合、継承関係を気にせずに実装でき、また、遠く離れたクラス同士で多態性を実現することが可能じゃ。

弟子D:なるほど、よくわかりました!

師匠T:うむ。弟子よ、ここまで13回、よく頑張ったのう。これはそのほうびじゃ。受け取るがよい。

弟子D:はいっ! あぁ、ついに俺も弟子を卒業……あれ?

『弟子D殿。貴殿を弟子10級から弟子9級に昇格する』

師匠T:ふっふっふっ。

師匠T:さて、ここまでJavaについてレクチャーしてきたが、Javaをマスターする道は長く、また一つではない。精進が必要じゃぞ。ではさらばぢゃ!



※次の更新は、9月17日・『師匠TのチャレンジARSゲーム!』の予定です。お楽しみに!
posted by 裏編 at 08:08| Comment(0) | 師匠のJava道場 | このブログの読者になる | 更新情報をチェックする

2018年08月14日

師匠のJava道場~第12回・師匠、例外とはなんぞや!?

師匠T:ジャッ、ヴァッ!!

弟子D:ドゥッ! ジョウッ!!

師匠T:うむ、いい汗をかいたのう、弟子よ。ということで、師匠Tである。

弟子D:弟子Dだぜっ! 今回は俺がしゅや……ぐはぁっ(師匠の飛び蹴り炸裂

師匠T:おぬしが主役など、2365年早いと何度も言っておるであろうが。さて、今回は、例外について説明する。準備はよいか?

弟子D:は、はい、師匠……

▽まず、例外とは?▽

弟子D:いきなりですが師匠。例外とはなんぞや。

師匠T:うむ。例外とは、いわゆるエラーのようなものじゃ。

弟子D:エラーのようなもの……ですか。

師匠T:うむ。Java……に限らず、他の言語でもそうだが、わしらが良く使う広義のエラーの概念は、昔の言語とは大きく違っておるのだ。

弟子D:それは一体?

師匠T:Javaでは、いわゆるエラーは二つに分かれておる。それが、例外とエラーじゃ。

弟子D:例外とエラー……ですか。それは、どう違うのですか?

師匠T:エラーとは、Javaでは手に負えない異常な出来事をさす。対して、例外とはJavaで扱える異常なことをさすのじゃ。

弟子D:ふむふむ。

師匠T:そして、この例外も二つにわかれておる。ランタイム系例外と、非ランタイム系例外じゃ。

弟子D:ランタイム系と、非ランタイム系……。ランタイムと、そうでないもの、という感じですか?

師匠T:そんな感じじゃな。具体的に言うと、ランタイム系は、コンパイルによってチェックされないもの、非ランタイム系は逆に、コンパイルによってチェックされる例外なのじゃ。

弟子D:なるほど。ちょっとややこしいですね。

師匠T:そんなときには、『いわゆる異常には、エラーと例外の二つがある』と覚えておけばよい。これでも、さほど問題はないからの。

弟子D:はい!

▽エラーの扱い方は……ない!▽

師匠T:エラーが出たときの対処法だが……

弟子D:ごくり。

師匠T:そんなものは、ない!!

弟子D:えええええええ!?

師匠T:エラーを、後述するtry~catchでとらえることはできる。じゃが、とらえたところでどうしようもないから、エラーが起きたら仕方ないと諦めるのが定例となっておる。

弟子D:そ、そうなのですか……。

▽例外を捕らえるtry~catchじゃ!▽

師匠T:そして例外の対処法じゃが……。

弟子D:まさか、そんなものはない、とかいうつもりじゃ……。

師匠T:安心するがよい。Javaには例外の発生が、プログラムの強制終了につながらないようにするための仕組みがある。それが、try~catch構文じゃ。

弟子D:try~catchですか。

師匠T:うむ。これは、発生した例外を捕らえ、そのときに処理を分岐させる構文なのじゃ。このようにして使う。

----------
try {
例外が発生するかもしれない処理
} catch (〇〇〇 e) {
〇〇〇例外が発生した時の処理
}
----------

師匠T:この構文では、まずtryとcatchの間の処理を行う。そして、〇〇〇に指定された例外が発生したときに、catchの下の処理を行うようになっておるのじゃ。

弟子D:なるほど。あの師匠、一つ質問が。

師匠T:なんじゃ?

弟子D:複数の種類の例外を捕らえたいときはどうするのですか?

師匠T:そのときには、catchの下に、さらに続けてcatchを書くのじゃ。このようにの。

----------
try {
〇〇〇

} catch (aaaException e) {
△△△

} catch (bbbException e) {
□□□

}
----------

弟子D:aaaExceptionが発生したら△△△の処理が、bbbExceptionが発生したら□□□の処理が実行されるわけですね?

師匠T:うむ。また、finallyというのもある。これは、例外が発生した、しないに関わらず、必ずその処理が終わったあと必ず実行する処理を書くものじゃ。このように使う。

----------
try {
〇〇〇

} catch (aaaException e) {
△△△

} catch (bbbException e) {
□□□

} finally {
×××
}
----------

師匠T:この例だと、例外が起こらなかった場合は、〇〇〇の処理を実行した後に×××の処理が実行され、例えばbbbExceptionが発生した後は、□□□の処理を実行した後に×××の処理が実行されるのじゃ。

弟子D:なるほど。

師匠T:なお、一度例外が発生して、catchの下に処理が移った場合、元のtryの下の処理に戻す方法はないので注意するのだ。

弟子D:はい!

▽例外のクラス構造じゃ!▽

師匠T:さて、ではここで例外のクラス構造について説明しておくとしようぞ。さて、例外のクラスの大本はExceptionだが、これのスーパークラスはThrowableクラスという。さらにこのThrowableの大本、スーパークラスは、わかるかな?

弟子D:むむむ……。

師匠T:第9回の講義を思い返すがよい。Throwableのスーパークラスは、全てのクラスの大本じゃ。それは何であった?

弟子D:あ! Objectクラスですね!

師匠T:うむ、そのとおりじゃ。さて、Throwableから派生したサブクラスとして、例外を表すExceptionクラスと、Errorクラスの二つがある。

弟子D:ふむふむ。

師匠T:そして、このExceptionクラスのサブクラスに、ランタイム系例外を表すRuntimeExceptionクラスがあるのじゃ。

弟子D:なるほど。あれ? 師匠、非ランタイム系例外は? ははーん、もうボケ……いてっ。

師匠T:たわけが。わしはまだ若い。非ランタイム系例外もちゃんと、Exceptionクラスのサブクラスとして存在しておる。

弟子D:な、なるほど……。

師匠T:このクラス構造は、この先のことについて重要となる。頭の片隅にでも入れておくがよい。

▽eとはなんぞや?▽

師匠T:さて、次はこの部分に注目じゃ。

----------
catch (aaaException e)
----------

師匠T:このeは、aaaExceptionで指定したExceptionクラスのインスタンスじゃ。いわば、発生した例外についての情報が入ったインスタンスなのじゃ。

弟子D:ふむふむ。

師匠T:なお、別に名前はeである必要はない。e1でもabcでもOKじゃ。さて、このインスタンスにはprintStackTraceメソッドが備え付けられておる。これを実行することで、例外が発生したメソッドに至るまでの、実行したメソッドの順番を表示することが可能じゃ。デバッグに役立つであろう。

弟子D:そうですね。覚えておくとします。

師匠T:うむ。

▽スーパークラス側の例外を補足じゃ!▽

師匠T:さて。

----------
catch (aaaException e)
----------

師匠T:この部分の、aaaExceptionのところには、普通はそれぞれの例外の型を書くものじゃが、その例外のスーパークラスを書くことも可能じゃ。例えば、ランタイム系例外を補足するときに、その例外の型ではなく、RuntimeExceptionクラスを指定する、という感じじゃな。

弟子D:ふむふむ。そうすることで、どんなメソッド……じゃなかったメリットがあるのでしょうか?

師匠T:うむ。これを利用することで、複数の例外を一つのcatchで捕らえ、処理することが可能じゃ。

弟子D:おぉっ!!

師匠T:ただし、その例外がどんな例外なのかがわかりにくくなるので、そこは気を付ける必要があるぞ。

弟子D:使い分けが大事、ということですね。わかりました!

▽throwsじゃ!▽

師匠T:さて、クラスを宣言する部分じゃが、これにはthrowsという言葉をつけることができる。

弟子D:それはどのようなもので?

師匠T:うむ。これは、『このメソッドで、これこれの例外が発生する可能性がある』が、『このメソッドでは、その例外の処理はしない』というのを表すものじゃ。これを利用する場合は、その例外は、別のメソッド(たいていは発生したメソッドの呼び出し元)で処理することになる。このような感じじゃな。

----------
void 〇〇〇() {
try {
△△△();
} catch (xxxException e) {
□□□

}
}

void △△△() throws xxxException {
×××

}
----------

弟子D:なるほど。

▽例外を投げるのじゃ!▽

師匠T:さて。Javaでは、発生した例外を捕らえ、処理するだけではない。オリジナルの例外を作り、発生させることができるのじゃ。なお、これを『例外を投げる』ともいう。

弟子D:なるほど。そのプログラム独自の例外を発生するのに使えそうですね。どのようにするのですか?

師匠T:うむ。それには、throwを使うのじゃ。このように使う。

----------
throw new [例外のクラス]

例:throw new MalformedURLException
----------

師匠T:例のように、既存の例外を投げることもできるぞ。他方、オリジナルの例外を作る場合は……
・ランタイム系例外を投げる→RuntimeExceptionクラスを継承するクラスを作り、投げる
・非ランタイム系例外を投げる→Exceptionクラス、またはRuntimeException以外の、Exceptionのサブクラスを継承するクラスを作り、それを投げる
のじゃ。例としては、このような感じじゃ。

----------
public class SisyoException extends RuntimeException {

}

public class Sisyo1 {
private static void abc() {
throw new SisyoException();
}
}
----------

弟子D:なるほど!

師匠T:ランタイム系例外を投げる場合、特段、コードを記述しなくても処理することができるが、プログラムが強制終了するリスクを負う。非ランタイム系を投げた場合は、そのようなリスクはないが、処理するためのコードを書く必要がある。
throwsで、そこでは処理しないことを明示するか、try~catchを書くか、ということじゃな。どっちを利用したほうがいいか、ケースバイケースなのでよく考えることが必要じゃ。

弟子D:はい、考えません、師匠!

師匠T:……(無言で弟子に飛び蹴り)さて、次回はいよいよ最終回。インターフェイスについて説明する。予習、復習はしっかりの。



※次の更新は、8月16日、『師匠TのチャレンジARSゲーム!』の予定です。お楽しみに!
posted by 裏編 at 09:26| Comment(0) | 師匠のJava道場 | このブログの読者になる | 更新情報をチェックする

2018年07月10日

師匠のJava道場~第11回・finalについて学ぶのじゃ!

師匠T:さてさて、この講座も10回を超えたか。ずいぶん歩んできたのう。

弟子D:はい。俺も、Javaのプログラミングについて、いくらか詳しくなったような気がします。

師匠T:言うようになったのう、こいつめ。まぁ、それもわしの見事な教えがあったればこそじゃな。

弟子D:……。

師匠T:ごほん。さて、今回は、final修飾子とについて説明していくとするぞ。

弟子D:はい、師匠!

▽まずはfinal修飾子についてじゃ!▽

師匠T:まず弟子Dに問題じゃ。finalという英語の意味とはなんぞや。

弟子D:えぇと、最後の、という意味でしたっけ。

師匠T:うむ。Javaでのfinalもそれと同じようなものじゃ。finalをつけると、そこから拡張や変更ができなくなるのだ。
どのようになるかは、これから説明していくぞ。

弟子D:はい!

師匠T:まずは、クラスやメソッドにつけた場合じゃ。これらにfinalをつけると、それらの継承やオーバーライドができなくなる。

弟子D:ふむふむ。

師匠T:これらの特性から、メソッドであっても、コンストラクタにはfinalをつけることはできない。注意しておくのじゃ。

Java1807-01.JPG
△ コンストラクタにfinalをつけるとエラーになるぞ!

師匠T:そして基本型の変数(フィールド)にfinalをつけた場合。このとき、この変数の値は変更することはできない。

弟子D:なるほど。

師匠T:なお、Javaでは、このようにして宣言された変数を定数として扱う。その場合、変数名は大文字で書くのが慣例じゃ。

弟子D:はい、わかりました!

師匠T:うむ、いい返事じゃ。さて、続いては、基本型の引数にfinalをつけた場合じゃ。これも同じように、その引数の値を変えることはできぬ。正確に言うと、変える命令を実行することはできるが、実際に値を変更することはできぬのじゃ。ほれ、この通り。

Java1807-02.JPG
△ 色が変わっている部分に注目。引数aの値を3に変えているが……。

Java1807-03.JPG
△ aの値は2のままだ!

弟子D:なるほど。

師匠T:なお、ローカル変数につけた場合も、フィールドと同じく、その値を変更することはできぬのだ。

弟子D:ふむふむ。あ、師匠。いまさらなんですが、ローカル変数とフィールドってどう違うので?

師匠T:うむ。それを説明し忘れておったの。どちらも、値を格納したり、インスタンスと結び付けたりといった機能は同じじゃが、ローカル変数は、そのメソッドの中でのみ有効で、メソッドを抜けると消滅してしまうもの、そしてフィールドは、メソッド外で宣言されたもので、そのクラス内ならどこからでも参照できるものを指すのじゃ。基本的にフィールドとは、そのインスタンスの特性を表すために使われておるな。

弟子D:なるほど、わかりました。

師匠T:うむ。さて、では続けるぞ。フィールド、ローカル変数問わず、参照型変数にfinalをつけた場合じゃ。

弟子D:はい。

師匠T:この場合、その変数の参照先(リンク先)を変えることはできない。しようとすると、エラーになるのじゃ。

Java1807-04.JPG
△ 参照型変数に、代入(参照型変数の場合は参照先の変更)しようとすると、エラーになるぞ!

師匠T:ただし、参照先の内容を直接変えるのならOKじゃ。

弟子D:なるほど、わかりました、師匠!

師匠T:うむ。次回は、Javaにおいて、クラスと並んで重要なポイントの一つ、例外について説明していくぞ。予習復習を忘れてはならぬ!



※次の更新は、7月12日。『師匠TのチャレンジARSゲーム!』の予定です。お楽しみに!
posted by 裏編 at 07:33| Comment(0) | 師匠のJava道場 | このブログの読者になる | 更新情報をチェックする

2018年06月07日

師匠のJava道場~第10回・抽象クラスを使うのじゃ!

弟子D:ど、どうなさったのですか、師匠? 何か黒いオーラが。

師匠T:いや、この間散歩しておったら、カップルがいっぱいな……いやなんでもない。気にするな。

弟子D:は、はぁ……(触らぬ神に……)

師匠T:さて、今回は抽象クラスについて説明する。覚悟はよいか?

弟子D:は、はい……。

▽抽象クラスとは?▽

弟子D:師匠、いきなりですが、抽象クラスとはなんぞや。

師匠T:うむ。抽象クラスとは、普通のクラスとは少し違っておって、継承されることを前提としたクラスじゃ。
 これには、次のような特徴があるぞ。

弟子D:ふむ。

師匠T:まず一つ。抽象クラスはインスタンスを作ることができない。

弟子D:つまり、例えば、Zakuクラスが抽象クラスだとして、そこからインスタンスのoZakuを作ることはできない、ということてすね? こんな風に。

----------
Zaku oZaku = new Zaku();
----------

師匠T:うむ、その通りじゃ。ただし、継承はできることを忘れてはならぬぞ。また二つ目の特徴として、抽象クラスは特別に、処理内容の中身を持たぬ、抽象なメソッド……ずばり抽象メソッドを持つことができる。
もちのろん、普通のメソッドを持つこともできるぞ。

弟子D:なるほど。でも、処理内容のないメソッドを用意して何になるんです?

師匠T:うむ、よい質問じゃの。例えば、複数のクラスの中で、ほぼ同じメソッドがあるとするじゃろ?

弟子D:はい。

師匠T:そうした場合、各クラスで別々のメソッド名にされては、管理が色々と困難になる。そこで、抽象クラス側で、そうしたメソッドを用意しておき、その処理は、この用意されたメソッドに書いてもらえばいい、というわけじゃ。
例えば、ZakuクラスもGoufクラスも、マシンガンを撃つ処理がある場合、スーパークラス側にMachineGunメソッドを用意しておき、どちらのクラスも、これを使ってもらえばいいというわけじゃな。

弟子D:なるほど!

師匠T:では次はいよいよ、抽象クラスの作り方、などについて説明するぞ!

▽抽象クラス、抽象メソッドを作るには?▽

師匠T:まずは、抽象クラスの作り方について説明していくとしよう。といっても簡単じゃ。クラス名の前に、abstractと描けばよい。

----------
例:abstract class Mobile Suits()
----------

弟子D:ふむふむ。

師匠T:そして、抽象メソッドの作り方じゃ。これもまた簡単で、メソッド名の前に、同じようにabstractをつければよい。

弟子D:ふむふむ。あ、publicとかprivateとか、型名とかの前と後、どちらに書けばいいんですか?

師匠T:おぉ、それがあったの。よくぞ気が付いた。

弟子D:忘れるなんて、師匠ももうと……。

師匠T:何か言ったか?

弟子D:いえ、なんでもありません……。

師匠T:ごほん。abstractは、それらの前に書けばよいのじゃ。この通り。

----------
例:abstract public void MachineGun();
----------

師匠T:この例の通り、抽象メソッドには、波かっこ({})もその処理も、何も書いてはならぬ。必ず、()の後、;で〆るのじゃ。

弟子D:ふむふむ。

師匠T:そして、ポイントをもう一つ。抽象メソッドを持たせれば、そのクラスは必ず抽象クラスになる。ゆえに……。

弟子D:そのクラスにも、abstractをつけなきゃならない、ということですね。

師匠T:さて。こうして作った抽象クラスを継承した場合、そのサブクラスは、次のいずれかになる。

(1) 抽象メソッドを全て実装(メソッドの処理内容を全て書く)した場合、通常のクラスになる。
(2) 抽象メソッドが一つでも実装されなかった場合、そのクラスも抽象クラスになる。

師匠T:このため、(2)に該当するクラスにも、abstractをつけなくてはならぬ。注意せよ。

弟子D:はい、師匠!

師匠T:なお、継承したサブクラスで、その抽象メソッドを使う場合は、いつも通りにそのまま使えばよい。

----------
※抽象クラス側
abstract public int Shot();


※サブクラス側
public int Shot() {

}
----------

▽参照型変数についてじゃ!▽

師匠T:このことについて話す前に、一つ教えておくべきことがある。前回、オブジェクト型の変数は、実際に中に何か入っているわけではなく、変数から、オブジェクトにリンクが張られている、と話したな?

弟子D:はい。

師匠T:このような変数を、『参照型変数』ともいう。覚えておくように。

弟子D:わかりました!

師匠T:うむ。さて、先ほど話した通り、抽象クラスからはインスタンスを作ることができぬ。じゃが、今話した参照型変数にすることはできるのじゃ。

----------
※MobileSuitsクラスは抽象クラスです。
Zaku oZaku = new MobileSuits(); はNG
MobileSuits oMS = new Zaku(); はOK
----------

弟子D:ふむふむ。

師匠T:これは、後に説明する多態性について重要なポイントなので、心の片隅にでも覚えておくがよい。

弟子D:はい、師匠!

▽thisについてなのじゃ!▽

師匠T:さて。それでは次は、抽象メソッドの実装についてじゃ。スーパークラスで宣言されたフィールド(変数)を、サブクラス側で利用したい場合は、次のように書く。

----------
this.〇〇〇
例:this.sisyo
----------

弟子D:なるほど! ところで、サブクラスってなんでしたっけ?

師匠T:はぁっ!!(飛び蹴り)

▽オーバーライドについてなのじゃ!▽

師匠T:さて、次は@overrideについてじゃ。これは、次の二つの使用法で使われる。

(1) 抽象メソッドを実装する
(2) 既にあるメソッドの内容を上書きする
(3) インターフェイスの抽象メソッドを実装する

師匠T:(3)については、後の講座で説明するぞ。さて、(1)については既に話したの?

弟子D:はい。処理内容が何もないメソッドの処理を実際に書く……でいいんでしたっけ?

師匠T:うむ、そのようなものと考えればよかろう。そして、(2)についてじゃが、例えば、RPGにおいて、戦闘終了後の処理で、既存のシステムでは経験値とお金だけが入るのだが、今度作るゲームでは、特別なポイントを増やしたい、という場合があったりするじゃろ?

弟子D:はい。

師匠T:そのような場合、その既存の処理を残し、その処理の後、特別なポイントを増やす、という手法が使われることがある。場合によっては、その処理を丸々書き換えることもあるがの。
このように、スーパークラスのメソッドを、サブクラス側で書き換えることを、オーバーライドというのだ。

弟子D:なるほど。

師匠T:さて、そのような場合に使われる@overrideじゃが、使い方はそう難しいことではない。対象となるメソッドのすぐ上に、これを書けばいいだけじゃ。

----------
@override
public void MachineGun()
{

----------

弟子D:なるほど、わかりました。師匠!

▽多態性についてなのじゃ!▽

師匠T:さて。では最後に、先ほど話した、多態性について話すとしようぞ。多態性とは一言で言ってしまえば、同じメソッドでも、クラスによって実際の処理が異なることを言う。

弟子D:???

師匠T:例えばじゃ。例えばモビルスーツのクラスと、そのサブクラスがあったとする。

弟子D:はい。

師匠T:そのサブクラスそれぞれに格闘戦を表すメソッドがあったとしても、それぞれのモビルスーツによって、どうやって格闘戦を行うかは違ってくるじゃろ? ザクはヒートホークじゃが、ガンダムはビームサーベル、モビルファイターは拳で、というようにの。

弟子D:なるほど!

師匠T:このように、それぞれによって、実際の内容が違うのが、多態性、ポリモーフィズムというのじゃ。覚えておくがよい。

弟子D:はい!

師匠T:さて、次回はfinal修飾子について説明する。予習復習を忘れてはならぬぞ。ふぅ……さすがに疲れたわい。

弟子D:師匠ももうと……。

師匠T:はぁっ!!(飛び蹴り)

※次の更新は、6月11日、『師匠Tのチャレンジ!ARSゲーム』の予定です。お楽しみに!
posted by 裏編 at 09:00| Comment(0) | 師匠のJava道場 | このブログの読者になる | 更新情報をチェックする

2018年05月10日

師匠のJava道場~第9回・クラスを継承するのじゃ!

師匠T:さて、今回はクラスについての話第二弾、継承について話すとするぞ。準備はよいか?

弟子D:はい、師匠! でも、クラスについての話であれば、前回にすればよかったような。

師匠T:筆者が勉強したのは、クラス→キャスト→継承の順番だったのじゃ、仕方なかろう。

弟子D:わかったような、わからんような。

師匠T:無理やりわかれ。では始めるぞ!

▽継承とはなんぞや?▽

師匠T:例えば、ゲームを作るときのことを考えてみよ。自機や敵に共通して、移動の処理があるが、二つのクラスそれぞれに移動の処理を書いていたら大変じゃの。

弟子D:そういえばそうですね。

師匠T:そんなとき、移動の処理を持つ共通のクラスを作り、それから自機や敵のクラスを作れば、移動させるときには、その処理を呼び出せばいいので楽ではないか?

弟子D:おぉ、それは確かにっ。

師匠T:これが継承の利点じゃ。そして話が前後してしまったが、継承とは、あるクラスを基にして別なクラスを作ることを言う。

弟子D:ガンダムで例えるなら、ザクを基にして、ザクキャノンや高機動型ザク、サイコミュ高機動試験型ザクを作るようなものですね!

師匠T:なぜおぬしがザクキャノンや高機動型ザクはまだしも、ビショップ(=サイコミュ高機動試験型ザク)のような、マニアックなMSのことを知っているかは置いといて、見事な例えじゃな、まさにその通りじゃ。

弟子D:師匠がビショップの名前を知っているのも十分謎ですが……。

師匠T:気にするな。さて、次は継承のやり方について説明することにするぞ!

▽継承のやり方じゃ!▽

師匠T:継承のやり方じゃが、とても簡単。クラス名の宣言のあとに、こうつければいいだけじゃ。

----------
extends [スーパークラス名]

例:
public ZakuCannon extends Zaku
----------

師匠T:前々回説明した通り、スーパークラスとは、あるクラスの基になったクラス、サブクラスとは、あるクラスを基にして作られたクラスを言う。例えば、ZakuクラスからZakuCannonクラスを作った場合、ZakuクラスはZakuCannonのスーパークラス、ZakuCannonクラスは、Zakuクラスのサブクラス、となるわけじゃ。

弟子D:ふむふむ。

師匠T:さてさて。継承してクラスを作った場合、スーパークラスのメソッドやフィールドは、private宣言されているものを除いて、全て継承される。例えば、前々回作ったZakuクラスからZakuCannonクラスを作った場合、Zakuクラスに備え付けられていたfireメソッドも、ZakuCannonクラスは自動的に持つことになるのじゃ。

弟子D:なるほど。コンストラクタはどうなのでしょう?

師匠T:残念ながら、コンストラクタは継承されぬ。じゃが、スーパークラスのコンストラクタを利用する方法はあるので安心するがよい。

▽Objectクラスじゃ!▽

師匠T:さて、次はObjectクラスについて語るとしようぞ。

弟子D:確か前回も出てきましたね。あらゆるクラスの親になるクラスでしたっけ。

師匠T:うむ、そのとおりじゃ。よく覚えておったの。このObjectクラスは、継承について大きな意味を持つ。

弟子D:それはどのような?

師匠T:うむ。継承させずにクラスを作るとき、当然ながら、extendsはつけぬな?

弟子D:はい。

師匠T:そのような場合、Javaは内部で自動的に、『extends Object』と補完するようになっておるのじゃ。このことについて、わしら開発者側は意識することはないがの。

弟子D:なるほど、よくわかりました!

▽継承のさいの注意点じゃ!▽

師匠T:さて、続いては、継承のさいに気を付けることについて語るとするぞ。まず一つは、継承を行うさい、スーパークラスにできるのは一つだけ。二つのクラスから継承して、サブクラスを作ることはできぬのじゃ。
例えるなら、Zakuクラスと、Goufクラスから継承して、ZakuGoufクラスを作る、なんてことはできぬのじゃ。

弟子D:それでは、そのようなものを作りたいときはどうすれば?

師匠T:うむ。そのような場合には、インターフェースというものを使う。じゃが、これの説明はあとに回すとしよう。

弟子D:はい。それで、今一つは?

師匠T:うむ。これが、難しくも重大なポイントじゃ。『[引数を持たないコンストラクタ]を持たないスーパークラスを継承するさいには、注意が必要』ということじゃ。

弟子D:それはどのようなことなのでしょう?

師匠T:うむ。そのようなクラスを継承するさい、コンストラクタを作らずに継承した場合、Javaは、勝手に『引数を持たないコンストラクタ』を補完してしまう。じゃが、スーパークラスはそのコンストラクタを持たぬゆえ、ビルドエラーになってしまうのじゃ。

弟子D:むむむ、なんか難しいですね。

師匠T:まぁ、難しければ、『[引数を持たないコンストラクタ]を持たないクラスを継承する場合、サブクラスのほうで、そんなコンストラクタを作ること』と覚えておけば問題はなかろう。

弟子D:ううう、わかりました、師匠。

▽スーパークラスの変数への紐づけじゃ!▽

師匠T:さて、この話をするさいに、一つ前提として覚えておくことがある。オブジェクト型の変数というものは、String型と同じように、オブジェクト(=インスタンス)へのリンクが張られた存在、ということじゃ。

弟子D:例えば、Zakuクラスの変数oZakuは、中に本当にZakuクラスのインスタンスが入っているわけではなく、インスタンスは別の場所にあり、変数からそのインスタンスへのリンクが張られている、ということですか?

師匠T:うむ、そういうことじゃ。さて、例えば、ある変数に、それと同じクラスのインスタンスをリンクすることができる……これは当然じゃな?

----------
※ZakuCannonは、Zakuのサブクラスです。
ZakuCannon CharsZaku = new ZakuCannon(~);
----------

弟子D:はい、そうですね。

師匠T:じゃが、ある変数に、そのクラスのサブクラスのインスタンスをリンクさせる、ということもできるのじゃ!

----------
Zaku GarmasZaku = new ZakuCannon(~);
----------

弟子D:な、なんと! それはすごいです、師匠!

師匠T:うむ、じゃが、この使い方をした場合、いくつか制限がある。まず一つ、作られるインスタンスは、作る際に指定したクラスのもので、リンク先の変数のクラスには影響されない、ということじゃ。つまり、上の例でいえば、作られるのはZakuCannonクラスで、Zakuクラスにはならん、ということじゃな。

弟子D:ちょっと難しいですけど、考えれば当然の話ですね。

師匠T:そして二つ目。リンク先の変数のクラスにないメソッドやフィールドは使うことはできない、というものじゃ。例えば、ZakuCannonクラスにLongShotメソッドというメソッドがあっても、この場合は使うことができぬ、ということじゃ。

弟子D:ふむふむ。

師匠T:そして最後。両方のクラスに同じメソッドがあった場合、インスタンスのクラス側のメソッドが実行される、ということじゃ。

弟子D:なるほど!

▽コンストラクタの補完その他じゃ!▽

師匠T:では、今回の講座のラストじゃ。クラスを作る場合、コンストラクタを省略した場合は、デフォルトコンストラクタが補完される。

弟子D:師匠、デフォルトコンストラクタとはいかに?

師匠T:デフォルトコンストラクタとは、コンストラクタがない場合、Javaが自動的に作ってくれるコンストラクタのことじゃ。次のような構造となっている。

----------
[クラス名]()
{

}

例:
Zaku()
{

}
----------

弟子D:引数を何も持たず、中身もないんですね。なぜこのようなものを?

師匠T:うむ。それは、コンストラクタを作った場合、Javaが自動的に、super()という命令を補完して、スーパークラスのコンストラクタを呼び出すようにしてくれるからじゃ。(コンストラクタを作らず、Javaがデフォルトコンストラクタを作った場合も含む)じゃが、元々スーパークラスにコンストラクタがないと、困ったことになる。そこで、コンストラクタを作らなかった場合、自動的にJavaがデフォルトコンストラクタを用意してくれる、というわけなのじゃ。

弟子D:なるほど。

師匠T:なお、super()の記述は、Javaの補完に任せず、自分で書くこともできる。その場合、コンストラクタの最初の行に書く必要がある。よいかな?

弟子D:はい、師匠!

師匠T:うむ、ではいよいよ最後じゃ。先ほど話した、スーパークラスのメソッドやフィールドを使いたい場合。これにもsuperを使う。その方法はこうじゃ。

----------
super.[メソッド名orフィールド名]

例:
super.x = 5;
super.fire();
----------

弟子D:superのあとに、ピリオドで区切って、メソッド名やフィールド名を書けばいいんですね。わかりました!

師匠T:うむ。さて、次回は、抽象クラスについて語ることにするぞ。予習、復習を欠かしてはならぬ!

※次回の更新は、5月14日、『師匠TのチャレンジARSゲーム!』の予定です。お楽しみに!
posted by 裏編 at 07:31| Comment(0) | 師匠のJava道場 | このブログの読者になる | 更新情報をチェックする