クラスの使い方
前回までの説明の中にクラスとは「設計図のようなものである」、と記載をしましたが、設計図だけでは実際に動かすことが出来ません。
実際に動かすためには設計図を元に物体を作る必要があります。
例えば上記のようなクラスがあったとしましょう。
このクラスを使いたい場合以下のような記載をします。
このように動かしたいクラスの中でオブジェクトを生成する必要があります。
基本的に他のクラスを動かしたい場合は以下の形式で生成することにより生成したクラスのメソッドを使用することが出来ます。
このように他のクラスのオブジェクトを生成することをインスタンス化と言います。
また、生成したオブジェクトの中に含まれるメソッドを使用する場合、以下のように記載します。
このプログラムを動かしてみるとMarioクラスのjumpメソッド、growメソッド、cowerメソッドの順に起動し、各メソッドの中に記載されているも文字列を出力することが出来ます。ところで…
new クラス名(引数)って何でしょう!?
こちらはこの後、明らかにしていきましょう。
コンストラクタ
ここではコンストラクタについて学んでいきましょう。
前章の最後で疑問にあがった new クラス名 (引数)
これはオブジェクトの生成時に使うものなのですが、一体どこから来ているのでしょう。
実はクラスの中には記載はされていないがコンストラクタというものが存在します。
実はこのクラスにも見えないコンストラクタというものが存在します。
このようにクラス名で出来たメソッドをコンストラクタといいます。
ただこのクラスではコンストラクタでは何の処理も行わないため記載する必要ないよねという状態になっているので記載していないのです。
主にコンストラクタではメンバ変数の初期化などに使われます。
以下のようなクラスを用意してみます。
このコンストラクタではオブジェクト作成時に名前、年齢、職業をメンバ変数に設定することでoutメソッドから出力することが出来ます。
オブジェクト指向とは
オブジェクト指向とは一体何なのでしょうか。
オブジェクト指向とは、単純に言ってしまうとオブジェクトを中心に考えてプログラミングを行うこと。
それ以上でもそれ以下でもありません。
ただし、その中でも「継承」「カプセル化」「ポリモーフィズム」の3つを原則を守る必要があります。
ではわかりやすいように説明していきましょう。
人間って何かわかりますか?
動物界 脊索動物門 脊椎動物亜門 哺乳綱 霊長目 真猿亜目 狭鼻下目 ヒト上科 ヒト科 ヒト亜科 ヒト族 ヒト亜族 ヒト属です。
人間をオブジェクトとして考えたとき以下のようになります。
各界門綱目科族が1つ上位の界門綱目科族の内容を「継承」しています。
また各界門綱目科族の特徴については外部から変更がかけられないよう「カプセル化」されています。
ヒト属が進化していく上でヒト亜族の枠を超えることがたまに存在します。
ただしそれはヒト亜族の中のヒト属のみだと仮定しましょう。
この場合ヒト属以外もヒト亜族を「継承」している属が存在しているとヒト亜族の内容を変えてしまうとヒト亜族以下の属すべてが同じ進化をしてしまったことになります。
このときヒト属からヒト亜族を「継承」する際にヒト属からヒト亜族を上書き(オーバーライド)します。
これを「ポリモーフィズム」(多様性、多相性、多態性)といいます。
このようにオブジェクト指向とは私たちが住んでいる現世のモデリングであることがわかります。
継承とは
ここでは継承について学んでいきます。
継承では親クラス(スーパークラス)の内容を引き継ぎ子クラスでも同じ内容を使用できるようにします。
例えば以下のようなクラスがあったとしましょう。
Human クラスでは人の年齢と性別と職業のみ管理しています。
あくまでただの人を示すクラスです。
では様々な職業についている人を示す場合どのようにすればいいのでしょうか。
このような内容を各職業に対して書くのめんどくさいし…ってなりますよね。
こんなときに継承を使います。
しかし Human クラスにはデフォルトコンストラクタ(引数のないコンストラクタ)がないため継承できません。
なので先にデフォルトコンストラクタを書いておきます。
これで問題ないです。
Human クラスを継承しクラスを作成してみましょう。
Human クラスを継承した三つのクラスを作ってみました。
では各クラスを用いてインスタンスを生成して表示してみましょう。
このプログラムを実行した際右側のものが出力されます。
このことから各クラスが Human クラスの name, gender, job と getAll メソッドを継承し各インスタンスから job の内容が書き換えられているのがわかります。
あとは各クラスに固有の内容を記載していきましょう。
カプセル化とは
カプセル化とはオブジェクトの構造をカプセル状にしてしまうことを指します。
なにをカプセル状にしてしまうかというとメンバ変数、つまりそのクラスで持っているパラメータを外部からいじれないようにします。
ソースを見てもらうとメンバ変数がすべてprivateなため外部クラスから直接変更が出来ないようになっています。
しかしこのままだと以下のようなことが出来てしまいます。
このように満腹度を200にしたり急に0にしたり出来てしまい不整合が起きてしまいます。
満腹度のような制限を設ける値には単純なゲッターやセッターでは対応しきれません。
なので異常な値を避けるため以下のように変更を加えていきます。
このようにゲッターセッターではなく食べるメソッドと走るメソッドに変えてみました。
しかしこれでもまだ足りないのです。
ほら、満腹度が0でも走り続けられちゃうでしょ?
むしろどんどんマイナスになってゲッソリどころの話ではなくなってしまいます。
ここまでやればやっと満腹度が0~100の間で収まるようになりますね。
これで中身が外部からいじれない完全なカプセル状になりました。
しかしカプセルにはもうひとつ意味があります。
「中身を守る」だけではなく「完成されている」というニュアンスも持っています。
これはオブジェクト自体が完成されたひとつの部品であるというニュアンスを持ちます。
外部からいじれたとしても完成されたひとつの部品であればカプセル化できていると言えるでしょう。
ポリモーフィズムとは
ポリモーフィズムとは引数を受け取ったインスタンスがそのクラスのよって違う振る舞いをすることをポリモーフィズム(多態性、多様性、多相性)と呼びます。
どういうことか説明していきましょう。
では前回までに使ったこのクラスたちを元に説明をしていきましょう。
このままだと説明出来ないので各クラス攻撃できるようなメソッドを追加していきます。
さてこんな感じで攻撃メソッドを追加してみました。
今回は実行する際以下のように実行してみます。
注目してみるところはインスタンス生成の部分です。
普段であれば別クラスに実装した機能を使うには継承、もしくはそのクラスのインスタンスを定義して使用します。
ですが今回はHumanクラスの参照変数に各クラスのインスタンスを代入しています。
つまりサブクラスのインスタンスをスーパークラス(親クラス)の参照変数に代入しています。
なぜこのような実装をする必要があるのでしょうか。
それは「共通のメソッドを呼び出すがオブジェクトによってその機能を変化させる」という点です。
実はこの機能がないと各サブクラスのインスタンスを別々に生成しないといけません。
それはサブクラスの参照変数に別のサブクラスのインスタンスを代入できないからです。
これを実装することで、1つのスーパークラスの参照変数に他のサブクラスのインスタンスを代入できるので統一した記述方法を使用しながら、それぞれのオーバーライドメソッドを呼び出すことが出来ます。
上記のコードを実行してみると以下のような出力がされます。
同じHumanクラスからattackメソッドを呼んでいるにもかかわらず違う出力内容が得られます。
これは継承しているクラスがHumanクラスのattackメソッドを上書きしているために起こります。
ちなみにメソッドの上書きを行うことをオーバーライドと呼びます。
このように引数を受け取ったインスタンスがそのクラスのよって違う振る舞いをすることをポリモーフィズム(多態性、多様性、多相性)と呼びます。
※最新の情報の取得・更新に努めておりますが、掲載内容については、その正確性、完全性、有用性、最新性等についていかなる保証もするものではありません。