Masayan tech blog.

  1. ブログ記事一覧>
  2. 【PHP】アニメ「NARUTO」でオブジェクト指向を説明してみる

【PHP】アニメ「NARUTO」でオブジェクト指向を説明してみる

公開日

NARUTOについて

忍者同士が超常的な能力「忍術」「体術」「幻術」「仙術」を駆使して派手な戦いを繰り広げるバトルアクション漫画です。

キャラ一人一人に個性があり、戦闘シーンも迫力があってとても面白いのですが、主人公のうずまきナルトが戦いの中で成長し、過去の先人たちが犯した過ちや失敗や苦難を乗り越え、真の平和・友好をもたらしていくというテーマがとても素敵です。

NARUTO -ナルト-』(ナルト)は、岸本斉史による日本漫画作品。またこれを原作とするアニメゲームなどの作品。『週刊少年ジャンプ』(集英社)にて1999年43号から2014年50号まで連載された。全700話

NARUTOでオブジェクト指向

NARUTOを読んだことがない方はぜひ読んでいただきたいところですが、ここからは本題のオブジェクト指向について説明していきます。

オブジェクト指向とは

関連するフィールドとフィールドを扱うメソッドをまとめたクラスファイルから、オブジェクト(インスタンス)を生成することを前提としたプログラミングの設計方法です。

オブジェクト指向に基づいて開発を行う最も大きな目的は"工数の削減"です。

開発が進んでいくと、"単に動くだけのプログラム"だけでは足りず、できる限り保守作業にかかる工数を抑えることができるように設計する必要があります。

プログラムにおいて工数を削減できる効果的な方法として、"汎用的なコードを作り、それを使い回す"ことが挙げられます。

抽象化

汎用的なコードを作るための工程として"抽象化"が挙げられます。
抽象化することで共通部分を切り出すことができ、共通部分を汎用的なコードとしてまとめてあげ、
実際に使用する際に共通しない部分(動的な値)を与えてコードを実行してあげれば一からコードを書く必要がなく、コードを書く作業を効率化することができるというわけです。

NARUTOを例に挙げると、主人公のライバルであるうちはサスケを抽象化する場合、抽象度をあげていくと以下のように変換できると思います。

うちはサスケ(抽象度低)

うちは一族

忍者

人間(抽象度高)

プログラミングによって"うちはサスケ"という実体を作る必要があるとなった場合、いきなり"うちはサスケ"用のクラス作ると非効率です。オブジェクト指向に沿って開発する場合は、まず抽象化したクラスである"人間クラス"を作成し、それを"継承"しながら(抽象度を高めながら)複数のクラスを作成していく方法が用いられます。

クラスを作る

人間 -> 忍者 -> うちは一族という順でクラスを作成し、うちはサスケというインスタンス(実体)を作成してみます。

クラス名

説明

Human

人間クラス。人間なので忍術を使うことはできない。あいさつと寝ることができる。

Ninja

人間ができることはできるし、チャクラを練って忍術を使うことができる。

UchihaClan

一般的な忍者ができることはでき、うちは伝承の写輪眼を使うことができる

人間クラス

classes/Human.php

<?php

// 人間クラス
class Human
{
    // フィールド
    protected $name;
    protected $clan;
    protected $amount_chakra;
    protected static $good_night = "Zzzz....";
    
    // コンストラクタ
    public function __construct(string $name, string $clan, int $amount_chakra)
    {
        $this->name = $name;
        $this->clan = $clan;
        $this->amount_chakra = $amount_chakra;
    }

    // 寝るメソッド
    public static function sleeping ()
    {
       print(self::$good_night. "<br>"); 
    }
    // あいさつするメソッド
    public function greeting()
    {
        print("あいさつする:" . "私の名前は" . $this->name."です。". "一族は" . $this->clan . 
          "です" . "<br>");
    }

    // チャクラを生成するメソッド
    public function generateChakra()
    {
        print("チャクラを練る:" . "私は忍者ではないのでチャクラを練ることができません" . 
          "<br>");
    }

    // 分身を作成するメソッド
    public function executeShadowCloningTechnique()
    {
        print("分身の術!!:" . "術を発動するためのチャクラが足りません");
    }
}
クラスの構成

関連するフィールドとフィールドを扱うメソッドの集まりです。(任意でコンストラクタも設定可能)
Humanクラスでは、名前、一族の種類、チャクラの量という抽象的なフィールドを用意し、そのフィールドの値を処理するメソッドを定義しています。

アクセス修飾子

アクセス修飾子は、カプセル化(情報隠蔽)の観点からとても重要なオブジェクト指向の概念の一つです。

その変数やメソッドを扱える範囲(アクセスできる範囲)を明確にしておくことは、バグの温床を取り除き、効率的で安定した開発を行う上では必須になります。

アクセス修飾子

指定したメンバやメソッドの使える範囲

指定なし

・メンバ変数は修飾子の指定がないとエラーになります。
・メソッドの場合はpublicを指定した場合と同じ扱いです。

public

クラスの内外どこからでも参照できる。

protected

宣言したクラス内と、継承したクラスから参照できる。

private

宣言したクラス内からしか参照できない。

static

フィールドやメソッドに"static"キーワードをつけると、静的なフィールドやメソッドを生成することができます。

staticキーワードをつけたフィールドとメソッドは以下のように、インスタンス化せずに直接アクセスすることができます

self::については後述します。

<?php>

// Bad
$human = new ();
$human->sleeping();

// Good
Human::sleeping();

new演算子でインスタンス化するメリットは、インスタンスごとに動的な値を渡して、具体性を向上させることですので、逆にいうと、動的でないフィールド(定数など)やメソッドはstaticをつけることでインスタンス化による無駄なメモリの消費や冗長な記述を防止することが可能です。

コンストラクタ

インスタンス作成時に値を受け取って動的な処理を行うことができます。
この__constructはマジックメソッドと呼ばれ、マジックメソッドは「特殊な状況で実行されるメソッド」のことです。

3-2.忍者クラス

classes/Ninja.php

<?php

// 人間クラスを継承した忍者クラス
class Ninja extends Human
{
  // チャクラを生成するメソッド(Humanクラスをオーバーライド)
  public function generateChakra()
  {
    $this->amount_chakra = 100;
    print("チャクラを練る:" ."チャクラ量が" .$this->amount_chakra . "になりました");
  }

  // 分身を作成するメソッド(Humanクラスをオーバーライド)
  public function executeShadowCloningTechnique()
  {
    $this->amount_chakra = $this->amount_chakra - 50;
    print("<br>". "分身の術!!:" . "分身を1体作りました。残りチャクラは" . $this->amount_chakra . "です" );
  }
}
継承

クラスは継承することができます。

今回の例だと、最も抽象的なHumanクラスから継承したNinjaクラスを作成することで簡単に忍者インスタンスを作成することが可能です。

継承元のクラスを「親クラス(スーパークラス)」。 継承してできる新しいクラスを「子クラス(サブクラス)」と呼びます

protected

前述のアクセサメソッドで触れたprotectedですが、スーパークラスでprotectedを付与したフィールドやメソッドは、サブクラスからアクセスすることができます。

$thisとself::

$thisは自分自身のオブジェクトを指し、インスタンス化した際、クラス内のメンバ変数やメソッドにアクセスする際に使用します。

上記に対し、self::は前述のstaticなメソッドから自クラス内のフィールドやメソッドにアクセスする際に使用します。

オーバーライド

Humanクラスで定義したメソッドをNinjaクラスで書き換えているのがわかるかと思います。
オーバーライドとは、親クラスで定義されているメソッドを子クラスで同じ名前のメソッドを作って定義し直す(再定義)することです

オーバーライドのメリット
・基本クラスから継承したメソッドの代わりに、派生クラスのメソッドを動作させることができる。
・1つのメソッド名でそのオブジェクトのクラスに応じて、適切な処理(メソッド)を行わせることができる。
・複数のメソッド名を定義したり覚えたりする必要がなくなる。

3-3.うちは一族クラスを作る

忍者クラスを継承してうちは一族クラスを作成しています。

classes/UchihaClan.php

<?php

// 忍者クラスを継承したうちは一族
class UchihaClan extends Ninja
{
  // メソッド
  public function executeSharingan()
  {
    $this->amount_chakra = $this->amount_chakra - 30;
    print( "<br>" . "写輪眼を発動!!" . "残りチャクラは" . $this->amount_chakra . "です");
  }
}

クラスからインスタンスを作る

ここまでで必要なクラスが準備できました。
実際にインスタンス化してオブジェクトを生成してみましょう。

以下の点がポイントです。

  • staticメソッドには、インスタンス化せずにアクセスできている
  • インスタンス時に、作成したいオブジェクトごとに動的な値を渡している

/index.php

<?php

require_once('./classes/Human.php');
require_once('./classes/Ninja.php');
require_once('./classes/UchihaClan.php');

// 人A
echo "<h3>村人A</h3>";
$name = "人A";
$clan = "不明";
$amount_chakra = 0;
Human::sleeping();
$human = new Human($name, $clan, $amount_chakra);
$human->greeting();
$human->generateChakra();
$human->executeShadowCloningTechnique();

// 忍者A
echo "<h3>忍者A</h3>";
$name = "忍者A";
$clan = "不明";
$amount_chakra = 100;
Ninja::sleeping();
$ninja = new Ninja($name, $clan, $amount_chakra);
$ninja->greeting();
$ninja->generateChakra();
$ninja->executeShadowCloningTechnique();


// うちはサスケ
echo "<h3>うちはサスケ</h3>";
$name = "うちはサスケ";
$clan = "うちは一族";
$amount_chakra = 100;

UchihaClan::sleeping();
$uchiha_clan = new UchihaClan($name, $clan, $amount_chakra);
$uchiha_clan->greeting();
$uchiha_clan->generateChakra();
$uchiha_clan->executeShadowCloningTechnique();
$uchiha_clan->executeSharingan();

クラスを使い回す

オブジェクト指向設計のメリットは、開発工数を削減できることです。試しに新しく日向一族のクラスを作成し、日向ネジのインスタンスを作成してみたいと思います。

まず、Ninjaクラスを継承したHyugaClan.php(日向一族クラス)を作成します。

<?php

// 忍者クラスを継承した日向一族
class HyugaClan extends Ninja
{
  // メソッド
  public function executeByakugan()
  {
    $this->amount_chakra = $this->amount_chakra - 30;
    print( "<br>" . "白眼を発動!!" . "残りチャクラは" . $this->amount_chakra . "です");
  }
}

次に、日向ネジのインスタンスを生成するコードをindex.phpに追記します。

index.php

// 日向ネジ
echo "<h3>日向ネジ</h3>";

$name = "日向ネジ";
$clan = "日向一族";
$amount_chakra = 100;

HyugaClan::sleeping();
$hyuga_clan = new HyugaClan($name, $clan, $amount_chakra);
$hyuga_clan->greeting();
$hyuga_clan->generateChakra();
$hyuga_clan->executeShadowCloningTechnique();
$hyuga_clan->executeByakugan();

こうすることで、既存の抽象的なクラスから簡単にキャラクターを生成することが可能です。

まとめ

本記事では、オブジェクト指向をPHPを用いて、NARUTOをもとに説明しています。抽象的な概念であるオブジェクト指向は初学者の方には理解しにくいものですが、アニメを用いて具体的に説明を行うことで、オブジェクト指向の基本的な考え方やメリットを理解していただけるのではないかとおもいますので、ぜひ参考にしてみてください。