今回がC#お勉強やろうの最終回となります。el(える)です。
今回はポリモーフィズムです。
なんだかさっぱりわかりません。
難しそうな名前ですね。覚えるために勉強しましょう。
目次
ポリモーフィズム編
ポリモーフィズム(多態性)とは、 派生クラスとインスタンスを基本クラスの変数に入れられる仕組み です。
もう何言っているか分からねぇぜ・・・
01シューティングゲームに必要なクラスを考える
自機のロケットから弾を撃って敵を破壊したり避けたりするゲームを例に考えます。
1.アプリケーション内で変化する可能性のあるものを書き出す
動くものとして自機のロケット、UFO、星、隕石としましょう。
2.書き出したものをそれぞれに属する値を列挙する
ロケットクラスの値としては移動速度、残りの機体数などが考えられます。
UFO、星、隕石は破壊されるまでの耐性(HP)、移動速度などが考えられます。
3.書き出したものそれぞれに対応する動作や処理を列挙する。
ロケットは敵を破壊したり避けたりするので、移動、攻撃メソッドが考えられます。
UFO、星、隕石は独自の動きをするので移動メソッドが考えられます。
今回はHPだけをメンバ変数として持たせます。
UFO、星、隕石はすべて同じようなメンバを持っています。
クラスごとに重複するプログラムがある場合は継承を使うことですっきり書けます。
UFO、星、隕石はHPと移動メソッドが重複しているので、敵クラスを作ります。
敵クラスとそれを継承したクラスの作り方に焦点を絞って説明します。
02基本クラスのメソッドを派生クラスで書き換える(メソッドオーバーーライド)
前回同様、新規プロジェクトを作ります。
プロジェクト名はShootingGameとします。
プロジェクトができたらEnemy、UFO、Star、Meteorクラスを作ります。
クラスファイルが追加できたらそれぞれにプログラムを入力してください。
基本クラスとしてEnemyを作成し、UFO、Star、Meteorクラスを派生させます。
まずはポリモーフィズムの性質を使わずに作ってみましょう
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ShootingGame { class Enemy { public int hp; //体力 //移動メソッド public virtual void Move() { } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ShootingGame { class UFO: Enemy { public override void Move() { Console.WriteLine("ジグザグに移動"); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ShootingGame { class Star: Enemy { public override void Move() { Console.WriteLine("回転しながら移動"); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ShootingGame { class Meteor: Enemy { public override void Move() { Console.WriteLine("まっすぐに移動"); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ShootingGame { class Program { static void Main(string[] args) { UFO ufo; Star[] stars = new Star[2]; Meteor[] meteors = new Meteor[2]; //インスタンスを作成する ufo = new UFO(); stars[0] = new Star(); stars[1] = new Star(); meteors[0] = new Meteor(); meteors[1] = new Meteor(); //敵を移動する ufo.Move(); for(int i = 0; i < stars.Length; i++) { stars[i].Move(); } for(int i = 0; i < meteors.Length; i++) { meteors[i].Move(); } } } }
メソッドオーバーライドとは
EnemyクラスにはUFO、Star、Meteorクラスに共通するメンバ変数hpと、メンバメソッドMoveを持たせています。
MoveメソッドはUFO、Star、Meteorクラスに継承されますが、
処理内容はそれぞれのクラスで異なります。
そのため、Enemyクラスではひとまず処理を書かずに定義しています。
派生クラスのメソッドの処理内容が、派生クラスごとに微妙に違うことはよくあります。
このような場合に便利なのが、メソッドオーバーライドです。
メソッドオーバーライドとは、
基本クラスから継承したメソッドを派生クラスで書き換えること です。メソッドをオーバーライドするには3点を満たす必要があります。
- 基本クラスのメソッドにvirtualキーワードをつける
- 派生クラスのメソッドにoverrideキーワードをつける
- メソッド名や引数、戻り値の型はvirtualキーワードをつけたメソッドと同じ
オーバーライドされる基本クラスのメソッドと、
オーバーライドする派生クラスのメソッドの書き方は次のようになります。
オーバーライドされる基本クラスのメソッドの書式
virtual 戻り値の型 メソッド名(引数)
{
メソッドの処理内容
}
オーバーライドする派生クラスのメソッドの書式
override 戻り値の型 メソッド名(引数)
{
メソッドの処理内容
}
オーバーライド(override)は優先するという意味です。
抽象クラス
Enemyはプレイヤの機体を妨げる何らかの物体という抽象的な意味合いのクラスで、
単独で何らかの機能を持つものではありません。
間違って誰かがこのクラスのインスタンスを作ってしまわないように、
インスタンス作成を禁止するマーク をつけておくことができます。インスタンス作成を禁止するマークの書式
abstract class クラス名
{
}
03ポリモーフィズムを使って書き換える
UFO、星、隕石は別クラスなので、それぞれのインスタンスをクラスごとの変数(ufo、stars、meteors)で管理しました。
宣言した変数ごとにMoveメソッドを呼び出す必要がありました。
ポリモーフィズムを使うと UFO、Star、MeteorクラスをEnemyクラスの配列1つで管理 できます。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ShootingGame { class Program { static void Main(string[] args) { Enemy[] enemies = new Enemy[5]; //インスタンスをEnemyクラスの変数に代入する enemies[0] = new UFO(); enemies[1] = new Star(); enemies[2] = new Star(); enemies[3] = new Meteor(); enemies[4] = new Meteor(); //敵を移動する for(int i = 0; i < enemies.Length; i++) { enemies[i].Move(); } } } }
ポリモーフィズムとは派生クラスのインスタンスを基本クラスの変数に入れることができる性質のことです。
UFOや星、隕石は同じ基本クラスから派生したクラスなので、
これらのインスタンスは敵クラスの変数に代入できます。
Moveメソッドを使って3種類の敵を動かしています。
UFO、Star、Meteorクラスのインスタンスはすべてenemies変数の配列に入れているので、
for文を1つ使ってMoveメソッドを呼び出せます。
終わりに
やべぇですな。
さっぱり分からんですよポリモーフィズム。
こんなに本を読んだのにサッパリ分からんのはすごい。
もう少し分かりやすい説明があればいいんだけど、
これも他の本を読み漁ったらいつの間にか覚えているものなのだろうか。。。
難しいのか僕の頭が阿呆なのか・・・
これが最後の勉強回なのにサッパリわからんとは・・・
まだまだ修行が足りないみたいです。。。
もっと精進せねば・・・
これまで僕が持っている本でおすすめしてきた本たちです。
どれも、初心者向けの本なので、
勉強するにはもってこいの入門書です。
勉強して知識を身につけましょう。
それではまた次回。