0
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

鬼滅で例えるクラス設計と書き方

0
Last updated at Posted at 2020-11-06

鬼滅の映画をみたのでせっかくなので学習中のプログラミングにも活用したいと思いました。
クラス設計に関してもっと色々理解したら拡張していく予定です。

前提

  • getterメソッドで長くなるので便宜上プロパティは全てpublicです
  • クラス、インスタンス、プロパティ、メソッド、コンストラクト、staticの記法がメイン(抽象クラスも少し)
  • フレームワークを使ってないので一部MVCの内容を同一ファイルに記述してます

abstract/interfaceの使い方を勉強した上でその上でもっと改良していきたいです。

こうした方が良いと言う箇所があればコメントいただけますと幸いです。
もし鬼滅をご存知の方であれば、できれば鬼滅で例えてもらえるとこの記事の品質向上にも繋げやすいので可能であればよろしくお願いしますm(_ _)m
鬼舞辻無惨をどこかに入れたかったです。

classとは

classとはプロパティ(変数)とメソッド(関数)をグルーピングしたもの。

変数や関数は、小規模開発の際は名前のつけたで管理できるが、人間なので、沢山できてくると関数や変数名を重複してうわがいてしまったり、やたら関数や変数名が長くなってしまったり、まったく関係ない処理を作りたいのに他の処理と競合してしまわないかと気を使ったりなど非効率なので、「商品情報を処理する変数と関数」「ユーザー情報を処理する変数と関数」「購入情報を処理する変数と関数」という処理に必要なプログラムをグルーピングして管理しやすくしよう!という先人の偉大な産物。
”設計書”と例えられることが多いが、”設計書”であるclass内のプロパティやメソッドを使うこともある。

設計

今回は以下クラス継承です。

Character (抽象クラス)
┗ → Oni (鬼) → Kizuki (十二鬼月)
┗ → Taishi (隊士) → Hashira (柱)
class_sekei.png
画像を新しいタブで開いていただくとと見やすいかもしれません。

抽象クラス(Character)

Character.php
<?php

//抽象class
abstract class Character
{
  abstract protected function attack();
}

?>
  • 先頭にabstractを付ける
  • 継承先でオーバーライドして欲しいメソッドにabstractと付ける
  • 抽象クラスはインスタンスを作れない

Oni,Kizukiクラス

※ この見出し以下のコードは全てOni.phpです。長いので分割してます。

Oniクラス

  • 別ファイルに記述した継承元の抽象クラスファイルを、冒頭でrequire_onceします。extendsで継承しましょう。
  • 全てのOniインスタンスに共通するプロパティはstaticをつけてクラスから取得できるようにしておきます。
  • 抽象クラスにあるattack()オーバーライド必須です。
  • __construct()メソッドに記述された処理はインスタンス作成と同時に処理が実行される(プロパティが勝手にセットされるので便利)
Oni.php
<?php

require_once "Character.php";

//Oniクラス
class Oni extends Character 
{
  //Property
  public static $count = 0;
  public static $blood = "鬼";
  public static $weak = "太陽光";
  public $name;
  public $sex;
  public $age;
  public $lifePoint;
  public $hitPoint;
  public $ateSum;

  //Function
  public function __construct($name,$sex,$age,$lifePoint,$hitPoint,$ateSum)
  {
    self::$count++;
    $this->name = $name;
    $this->sex = $sex;
    $this->age = $age;
    $this->lifePoint = $lifePoint;
    $this->hitPoint = $hitPoint;
    $this->ateSum = $ateSum;
  }

  public function attack()  //オーバーライドするため必ず書かないとエラーになるメソッド
  {
    return "継承元の抽象クラスCharacterのattack()をオーバーライド";
  }

  public function eat()
  {
    return "捕食数を増やすメソッド";
  }

  public function recover()
  {
    return "lifePointを増やすメソッド";
  }

}

Kizukiクラス

  • Oniクラスをextendsで継承しましょう。
  • Oniクラスのプロパティとメソッドは引き継いでいるので、十二鬼月にのみ追加で必要なプロパティとメソッドを追加
Oni.php
//Kizukiクラス
class Kizuki extends Oni
{
  //Property
  public static $count = 0;
  public static $category = "十二鬼月";
  public $number;
  
  //Function
  public function __construct($name,$sex,$age,$lifePoint,$hitPoint,$ateSum,$number)
  {
    self::$count++;
    $this->name = $name;
    $this->sex = $sex;
    $this->age = $age;
    $this->lifePoint = $lifePoint;
    $this->hitPoint = $hitPoint;
    $this->ateSum = $ateSum;
    $this->number = $number;
  }

  public function order()
  {
      return "鬼に命令するメソッド";
  }
}

2つのクラスのインスタンスを作成

  • インスタンスのプロパティの値は配列で渡すためReflectionClass(インスタンス名)->newInstanceArgsを活用。
  • 値がインスタンスの配列をreturn
Oni.php
function createOni()
{
    //Oniデータ
    $oni_list = [
    "yasamaru" => ["朱紗丸","f",16,25,20,23],
    "yahaba" => ["矢琶羽","m",18,20,35,9],
    ];
    //Oni配列を作成
    $data=[];
    foreach($oni_list as $key => $value)
    {
        $oni = new ReflectionClass("Oni"); //instance作成
        $instance = $oni->newInstanceArgs($value); //引数にプロパティ値の配列を渡す
        $data[] = $instance; //Oniインスタンスの配列を作成
    }
    return $data;
}

function createKizuki()
{
    //Kizukiデータ
    $kizuki_list = [
    "kokushibou" => ["黒死牟","m",27,250,150,450,"壱"],
    "douma" => ["童磨","m",24,220,135,420,"弐"],
    "akaza" => ["猗窩座","m",18,180,100,380,"参"],
    ];
    //Kizuki配列を作成
    $data=[];
    foreach($kizuki_list as $key => $value)
    {
        $kizuki = new ReflectionClass("Kizuki"); //instance作成
        $instance = $kizuki->newInstanceArgs($value); //引数にプロパティ値の配列を渡す
        $data[] = $instance; //Oniインスタンスの配列を作成
    }
    return $data;
}

//実行
$data_Oni = createOni();
$data_Kizuki = createKizuki();

Taishi,Hashiraクラス

※ この見出し以下のコードは全てOni.phpです。長いので分割してます。
※ Oni,Kizukiクラスと流れが同じなのでコードだけ貼ります。

Taishiクラス

Taishi.php
<?php

require_once "Character.php";

//Taishiクラス
class Taishi extends Character 
{
  //Property
  public static $count = 0;
  public static $blood = "人間";
  public static $weak = "鬼の血";
  public $name;
  public $sex;
  public $age;
  public $lifePoint;
  public $hitPoint;

  //Function
  public function __construct($name,$sex,$age,$lifePoint,$hitPoint)
  {
    self::$count++;
    $this->name = $name;
    $this->sex = $sex;
    $this->age = $age;
    $this->lifePoint = $lifePoint;
    $this->hitPoint = $hitPoint;
  }

  public function attack()  //オーバーライドするため必ず書かないとエラーになるメソッド
  {
    return "継承元の抽象クラスCharacterのattack()をオーバーライド";
  }
}

Hashiraクラス

Taishi.php
/Hashiraクラス
class Hashira extends Taishi
{
  //Property
  public static $count = 0;
  public static $category = "鬼殺隊";
  public $type;
  public $tsuguko;
  
  //Function
  public function __construct($name,$sex,$age,$lifePoint,$hitPoint,$type,$tsuguko)
  {
    self::$count++;
    $this->name = $name;
    $this->sex = $sex;
    $this->age = $age;
    $this->lifePoint = $lifePoint;
    $this->hitPoint = $hitPoint;
    $this->type = $type;
    $this->tsuguko = $tsuguko;
  }

  public function tsuguko()
  {
      return "継子を交換するメソッド";
  }
}

2つのクラスのインスタンスを作成

Taishi.php
function createTaishi()
{
    //Taishiデータ
    $taishi_list = [
    "tanjiro" => ["竈門 炭治郎","m",15,12,32],
    "zenitsu" => ["我妻 善逸","m",16,10,28],
    "inosuke" => ["嘴平 伊之助","m",15,15,30],
    ];
    //Taishi配列を作成
    $data=[];
    foreach($taishi_list as $key => $value)
    {
        $taishi = new ReflectionClass("Taishi"); //instance作成
        $instance = $taishi->newInstanceArgs($value); //引数にプロパティ値の配列を渡す
        $data[] = $instance; //Taishiインスタンスの配列を作成
    }
    return $data;
}

function createHashira()
{
    //Hashiraデータ
    $hashira_list = [
    "giyuu" => ["冨岡 義勇","m",21,18,34,"水柱","なし"],
    "shinobu" => ["胡蝶 しのぶ","f",18,10,21,"蟲柱","栗花落 カナヲ"],
    "kyoujyurou" => ["煉獄 杏寿郎","m",20,22,35,"炎柱","なし"],
    "tengen" => ["宇髄 天元","m",23,20,40,"音柱","なし"],
    "muichirou" => ["時透 無一郎","m",14,22,12,"霞柱","なし"],
    ];
    //Hashira配列を作成
    $data=[];
    foreach($hashira_list as $key => $value)
    {
        $hashira = new ReflectionClass("Hashira"); //instance作成
        $instance = $hashira->newInstanceArgs($value); //引数にプロパティ値の配列を渡す
        $data[] = $instance; //Hashiraインスタンスの配列を作成
    }
    return $data;
}

//実行
$data_Taishi = createTaishi();
$data_Hashira = createHashira();

View

index.php
<?php
require_once('Oni.php');
require_once('Taishi.php');
?>

<!DOCTYPE html>
<html>

<head>
    <meta charest="UTF-8">
    <title>鬼滅で例えるclassとinstance</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css"
        integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">
    <style>
        .red {color: red}
        .blue {color: blue}
        .green {color: green}
        #ONI {padding: 15px;}
        #TAISHI {padding: 15px;}
        th,td {text-align: center}
    </style>
</head>

<body>
    <section id="ONI">
    <h1>Character→Oni→Kizuki</h1>
    <hr>
    <h2>Oniインスタンス</h2>
   <p>数→<?=Oni::$count ?> / 血→<?=Oni::$blood ?> / 弱点→<?=Oni::$weak ?></p> <!-- staticプロパティを取得 -->
    <table class="table table-striped">
        <tr>
            <th>name</th>
            <th>sex</th>
            <th>age</th>
            <th>lifePoint</th>
            <th>hitPoint</th>
            <th>ateSum</th>
            <th class="red">attack()</th>
            <th>eat()</th>
            <th>recover()</th>
        </tr>
    <?php foreach ($data_Oni as $key => $value){ ?> 
        <tr>
            <td><?=$value->name ?></td>
            <td><?=$value->sex ?></td>
            <td><?=$value->age ?></td>
            <td><?=$value->lifePoint ?></td>
            <td><?=$value->hitPoint ?></td>
            <td><?=$value->ateSum ?></td>
            <td><?=$value->attack() ?></td>
            <td><?=$value->eat() ?></td>
            <td><?=$value->recover() ?></td>
        </tr>
    <?php } ?>
    </table>

    <h2>Kizukiインスタンス</h2>
   <p>数→<?=Kizuki::$count ?> / 血→<?=Kizuki::$blood ?> / 弱点→<?=Kizuki::$weak ?> / <span class="blue">カテゴリ→<?=Kizuki::$category ?></span></p>
    <table class="table table-striped">
        <tr>
            <th>name</th>
            <th>sex</th>
            <th>age</th>
            <th>lifePoint</th>
            <th>hitPoint</th>
            <th>ateSum</th>
            <th class="green">number</th>
            <th>attack()</th>
            <th>eat()</th>
            <th>recover()</th>
        </tr>
    <?php foreach ($data_Kizuki as $key => $value){ ?> 
        <tr>
            <td><?=$value->name ?></td>
            <td><?=$value->sex ?></td>
            <td><?=$value->age ?></td>
            <td><?=$value->lifePoint ?></td>
            <td><?=$value->hitPoint ?></td>
            <td><?=$value->ateSum ?></td>
            <td><?=$value->number ?></td>
            <td><?=$value->attack() ?></td>
            <td><?=$value->eat() ?></td>
            <td><?=$value->recover() ?></td>
        </tr>
    <?php } ?>
    </table>
 </section>
 

  <section id="TAISHI">
    <h1>Character→Taishi→Hashira</h1>
    <hr>
    <h2>Taishiインスタンス</h2>
   <p>数→<?=Taishi::$count ?> / 血→<?=Taishi::$blood ?> / 弱点→<?=Taishi::$weak ?></p>
    <table class="table table-striped">
        <tr>
            <th>name</th>
            <th>sex</th>
            <th>age</th>
            <th>lifePoint</th>
            <th>hitPoint</th>
            <th class="red">attack()</th>
        </tr>
    <?php foreach ($data_Taishi as $key => $value){ ?> 
        <tr>
            <td><?=$value->name ?></td>
            <td><?=$value->sex ?></td>
            <td><?=$value->age ?></td>
            <td><?=$value->lifePoint ?></td>
            <td><?=$value->hitPoint ?></td>
            <td><?=$value->attack() ?></td>
        </tr>
    <?php } ?>
    </table>

    <h2>Hashiraインスタンス</h2>
   <p>数→<?=Hashira::$count ?> / 血→<?=Hashira::$blood ?> / 弱点→<?=Hashira::$weak ?> / <span class="blue">カテゴリ→<?=Hashira::$category ?></span></p>
    <table class="table table-striped">
        <tr>
            <th>name</th>
            <th>sex</th>
            <th>age</th>
            <th>lifePoint</th>
            <th>hitPoint</th>
            <th class="green">type</th>
            <th class="green">tsuguko</th>
            <th class="red">attack()</th>
            <th>tsuguko()</th>
        </tr>
    <?php foreach ($data_Hashira as $key => $value){ ?> 
        <tr>
            <td><?=$value->name ?></td>
            <td><?=$value->sex ?></td>
            <td><?=$value->age ?></td>
            <td><?=$value->lifePoint ?></td>
            <td><?=$value->hitPoint ?></td>
            <td><?=$value->type ?></td>
            <td><?=$value->tsuguko ?></td>            
            <td><?=$value->attack() ?></td>
            <td><?=$value->tsuguko() ?></td>
        </tr>
    <?php } ?>
    </table>
 </section>

</body>
</html>

実行画面

  • 赤文字は抽象クラスから継承されているメソッドです。
  • 青文字はstaticプロパティをクラス名::プロパティ名クラスから直接取得しています。
  • 緑文字は継承元クラスにはない、追加したプロパティです。

鬼と十二鬼月のインスタンスデータ

スクリーンショット 2020-11-06 18.09.46.png

隊士と柱のインスタンスデータ

スクリーンショット 2020-11-06 18.09.56.png

記事

require_onceについて
https://qiita.com/v97ug/items/d058f69b1cf6f606aad2

0
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?