プログラミング

ピカチュウから学ぶオブジェクト指向 〜トレイト編〜 4

PHP PHPポケモン オブジェクト指向 ポケモン
ピカチュウから学ぶオブジェクト指向 〜トレイト編〜 4

 

ピカチュウから学ぶオブジェクト指向の第4弾は「トレイト(trait)の活用」についてです。更に、レベルシステムを導入すれば欠かせない経験値システムも合わせて実装します。

第3回からの続きとなりますので、もし前回をまだ見ていない人は是非ご参考ください。

ピカチュウから学ぶオブジェクト指向 〜レベルシステム導入編〜 3 ピカチュウから学ぶオブジェクト指向 〜レベルシステム導入編〜 3

  大人気?シリーズ「ピカチュウから学ぶオブジェクト指向」、今回はレベルシステムの導入編です。   第1回(基礎編)、第2回(クラス継承編)で作成したPokemonとPikachuのクラスを使用するので、最初から学習したい人はぜひご参考ください。 [shortcode_url_og url="https://s-yqual.com/blog/1035"...

 

それでは今回もピカチュウと一緒に、楽しくプログラミング、オブジェクト指向を学習しましょう。

 

 

トレイト(trait)とは

 

 

トレイトは、PHP のような単一継承言語でコードを再利用するための仕組みのひとつです。 トレイトは、単一継承の制約を減らすために作られたもので、 いくつかのメソッド群を異なるクラス階層にある独立したクラスで再利用できるようにします。 トレイトとクラスを組み合わせた構文は複雑さを軽減させてくれ、 多重継承や Mixin に関連するありがちな問題を回避することもできます。

 

トレイトはクラスと似ていますが、トレイトは単にいくつかの機能をまとめるためだけのものです。 トレイト自身のインスタンスを作成することはできません。 昔ながらの継承に機能を加えて、振る舞いを水平方向で構成できるようになります。 つまり、継承しなくてもクラスのメンバーに追加できるようになります。

 

 

だそうです。簡単にまとめるなら

継承しなくても使えるよ!インスタンスも作れないよ!なクラス

 といったところでしょう。

汎用性のあるメソッドをまとめておくイメージです。今回作っているようなポケモンのクラスでも使え、アイテムというクラスでも使えるようなメソッドも場合によっては必要になります。そういったものを毎回書かなくても良いようにまとめて置くのがトレイトの本来の使い方です。

 

 

トレイトの活用

 

前回(第3回)でファイルを分割しましたが、それでも記述量は多くなってきました。特にポケモンクラス内のメソッドが回数を重ねるごとに増えていきます。そこで、今回はトレイト(trait)を使って管理をします。

 

現在ポケモンクラス内にあるメソッドでは「get〜」という取得用のメソッドと、「set〜」という値を格納するようのメソッドで構成されています。なので、get関係set関係をそれぞれまとめて置くように「SetTrait」と「GetTrait」を作成しましょう。作成箇所は以下の通りです。

/Trait/GetTrait.php
/Trait/SetTrait.php

 

それではそれぞれのファイル内を見ていきましょう。

 

Get関係の格納トレイト(/Trait/GetTrait.php
<?php
trait GetTrait
{
 
    /**
    * 正式名称を取得する
    * @return string
    */
    public function getName()
    {
        return $this->name;
    }
 
    /**
    * ニックネームを取得する
    * @return string
    */
    public function getNickname()
    {
        if(empty($this->nickname)){
            return $this->name;
        }
        return $this->nickname;
    }
 
    /**
    * 覚えている技の一覧を取得する
    * @return array
    */
    public function getMove()
    {
        return $this->move;
    }
 
    /**
    * 現在のレベルを取得する
    * @return integer
    */
    public function getLevel()
    {
        return $this->level;
    }
 
}

 

Set関係の格納トレイト(/Trait/SetTrait.php
<?php
trait SetTrait
{
    /**
    * ニックネームを付ける
    * @return string
    */
    public function setNickname($nickname)
    {
        if(empty($nickname) || mb_strlen($nickname, 'UTF-8') > 5){
            echo 'ニックネームは1〜5文字で入力してください';
            return;
        }
        $this->nickname = $nickname;
    }
 
    /**
    * レベルをセットする
    * @return void
    */
    protected function setLevel()
    {
        // 初期レベルからランダムで値を取得
        $key = array_rand($this->default_level);
        $this->level = $this->default_level[$key];
    }
 
    /**
    * 初期技をセットする
    * @return void
    */
    protected function setDefaultMove()
    {
        foreach($this->level_move as list($level, $move)){
            if($level <= $this->level){
                // 現在レベル以下の技であれば習得
                $this->setMove($move);
            }else{
                // 現在レベルを超えていれば処理終了
                break;
            }
        }
    }
 
    /**
    * 技を覚える
    * @return string
    */
    public function setMove($move)
    {
        $this->move[] = $move;
        if(count($this->move) > 4){
            unset($this->move[0]);
        }
    }
 
}

 

それぞれgetsetのメソッドを移動してきました。それではトレイトの宣言部分について確認しましょう。

trait GetTrait

 

クラスとの大きな違いは最初の行にあります。クラスの場合はclassと宣言してからクラス名をつけますが、トレイトの場合はtraitと宣言してトレイト名をつけます。その他の記述方法はほとんど同じですが、宣言が違うということを覚えておきましょう。そして最初の説明でも述べたように、トレイトはインスタンス化(実体化)することができません

 

 

トレイトの読み込み

 

次に、クラスに対してトレイトを読み込む方法を見ていきましょう。今回はどちらもポケモンクラス内で使用していたメソッドなので、ポケモンクラス上で作成した2つのトレイトを読み込みます。

 

ポケモンのクラス(/Class/Pokemon.php
<?php
 
require_once('Trait/SetTrait.php');
require_once('Trait/GetTrait.php');
 
// ポケモン
abstract class Pokemon
{
    use SetTrait;
    use GetTrait;
 
    /**
    * ニックネーム
    * @return string(min:1 max:5)
    */
    protected $nickname;
 
    /**
    * 現在のレベル
    * @var integer(min:2 max:100)
    */
    protected $level;
 
    /**
    * 覚えている技
    * @var array
    */
    protected $move = [];
 
}

 

require_onceで使用するトレイトファイルを読み込みクラス内でトレイトの使用を宣言しています。

use SetTrait;
use GetTrait;

 

注意点は、useをクラス内で使用するということです。現在はまだ紹介していませんが、名前空間やオートローダーを使用するとクラスの前にuseをつけて必要ファイルを読み込みます。それに対して、トレイトの使用宣言はクラス内で行います。

 

これでポケモンのクラスで各トレイトに割り当てたメソッドが使用できるようになりました。ポケモンのクラスで使用できるということは、それを継承しているピカチュウのクラスでも呼び出すことができます。出力用ファイル(index.php)に記述して確認してみましょう。

 

出力用ファイル(index.php
<?php

require_once('Class/Pikachu.php');

$pikachu = new Pikachu;
$pikachu->setNickname('ピカイチ');

?>

<p>ニックネーム:<?=$pikachu->getNickname()?></p>

 

出力結果は以下の通りです。

# 出力結果
 
ピカチュウをゲットした
 
ニックネーム:ピカイチ

 

 

経験値システムの導入

 

レベルシステムにとって欠かせないのが経験値システムです。その初期準備として、初期経験値の計算と次のレベルアップに必要な経験値の算出を実装します。

そのために、まずポケモンの経験値の仕組みを見てみましょう。 

 

今回はリンク先の「経験レベルと必要経験値の換算表」という部分を参考にします。ポケモンによって異なるようですが、今回は最も単純なピカチュウの経験値タイプでもある「100万型」を実装します。

 

100万型経験値の計算方法は以下の通りです。

必要経験値 = Lv^3

 

もう少しわかりやすく表現すると

必要経験値 = レベル x レベル x レベル

 

上記の式が成り立ちます。PHP(5.6以降)であれば**演算子が使えるので、今回作成しているポケモンシステムであれば、以下の式で現在のレベルに必要な経験値を算出します。

$this->level ** 3

 

 

デフォルト経験値

 

ポケモンは捕まえた時点で、そのレベルに応じた経験値を所有していなければなりません。そのために、経験値を格納しておくプロパティ、デフォルト経験値の算出用メソッド、現在の経験値を取得するメソッドの3つを用意します。

 

  1. 経験値を格納するプロパティ
    ポケモンのクラス(/Class/Pokemon.php)
  2. デフォルトの経験値を算出するメソッド
    Set格納トレイト(/Trait/SetTrait.php) 
  3. 現在の経験値を取得するメソッド
    Get格納トレイト(/Trait/GetTrait.php)

 

ポケモンのクラス(/Class/Pokemon.php
/**
* 経験値
* @var integer
*/
protected $ex_point;

 

Set格納トレイト(/Trait/SetTrait.php
/**
* 初期経験値をセットする
* @return void
*/
protected function setDefaultExPoint()
{
    $this->ex_point = $this->level ** 3;
}

 

Get格納トレイト(/Trait/GetTrait.php
/**
* 現在の経験値を取得する
* @return integer
*/
public function getExPoint()
{
    return $this->ex_point;
}

 

setDefaultExPointのメソッドは、ポケモンを捕まえた時点で実行される必要がありますので、ピカチュウのクラスのコンストラクタで実行しましょう。

 

ピカチュウのクラス(/Class/Pikachu.php
/**
* インスタンス作成時に実行される処理
*/
public function __construct()
{
    $this->setLevel();
    $this->setDefaultExPoint();
    $this->setDefaultMove();
    echo 'ピカチュウをゲットした';
}

 

setDefaultExPoint内でレベルのプロパティ($this->level)が使用されています。なので実行するタイミングはsetLevelのあとでなければなりません

 

では、ピカチュウのインスタンスを作成して、経験値を実行ファイルで確認してみましょう。

 

実行ファイル(/index.php
# 出力結果(1回目)
 
ピカチュウをゲットした
 
現在のレベル:8
現在の経験値:512
# 出力結果(2回目)
 
ピカチュウをゲットした
 
現在のレベル:9
現在の経験値:729

 

換算表で確認してみると、レベル8では512レベル9では729となっているため正常に算出出来ていることがわかります。 

 

これで、初期経験値の設定は完了です。

 

 

次のレベルまで

 

ポケモンの経験値で気になるのは、現在の値よりも次のレベルまでに必要な値です。なので、次のレベルまでの値を算出するメソッドをGet格納トレイトに追加します。

 

Get格納トレイト(/Trait/GetTrait.php
/**
* 次のレベルに必要な経験値
* @return integer
*/
public function getReqLevelUpExPoint()
{
    return ($this->level + 1) ** 3 - $this->ex_point;
}

 

次のレベルまでに必要な経験値の算出方法は以下の通りです。

次のレベルまでに必要な経験値

= 次のレベルで必要な経験値 現在の経験値

 

現在の経験値は$this->ex_pointに格納されています。次のレベルで必要な経験値は以下の式で算出できます。

次のレベルで必要な経験値

= (現在のレベル + 1)の3乗

 

1列にまとめているので複雑な式に見えてしまうかも知れませんが、やっていることは至って単純です。算出式が、以下の通りです。

($this->level + 1) ** 3 - $this->ex_point

 

それでは出力結果を確認してみましょう。

 

実行ファイル(/index.php
<?php

require_once('Class/Pikachu.php');

$pikachu = new Pikachu;

?>

<p>現在のレベル:<?=$pikachu->getLevel()?></p>
<p>現在の経験値:<?=$pikachu->getExPoint()?></p>
<p>次のレベルまでに必要な経験値:<?=$pikachu->getReqLevelUpExPoint()?></p>
# 出力結果
 
ピカチュウをゲットした
 
現在のレベル:7
現在の経験値:343
次のレベルまでに必要な経験値:169

 

現在の経験値(343)と次のレベルまでに必要な経験値(169)を足すと、レベル8で必要な経験値(512)になるので正常に出力されていることがわかります。

 

これで、次のレベルまでに必要な経験値の出力設定が完了です。

 

 

詳細の取得

 

機能が増えてくれば、一つずつ出力するのは一苦労です。なので、一気に詳細を出力できるようなメソッドを作成します。Get格納トレイトに以下を追加しましょう。

 

Get格納トレイト(/Trait/GetTrait.php
/**
* 詳細を取得する
* @return integer
*/
public function getDetails()
{
    return [
        '正式名称' => $this->getName(),
        'ニックネーム' => $this->getNickName(),
        '現在のレベル' => $this->getLevel(),
        '覚えている技' => implode(',', $this->getMove()),
        '現在の経験値' => $this->getExPoint(),
        'レベルアップに必要な経験値' => $this->getReqLevelUpExPoint(),
    ];
}

 ※配列キーに日本語が用いられることはほとんど有りませんが、今回はわかりやすさ重視のために日本語を使用しています。気になる人は値として格納してlistで取得するなどしてください

 

それでは返り値として準備された配列を見てみましょう。

return [
    '正式名称' => $this->getName(),
    'ニックネーム' => $this->getNickName(),
    '現在のレベル' => $this->getLevel(),
    '覚えている技' => implode(',', $this->getMove()),
    '現在の経験値' => $this->getExPoint(),
    'レベルアップに必要な経験値' => $this->getReqLevelUpExPoint(),
];

 

返却する内容は至って単純です。それぞれの取得用メソッドに見出しとなるキーを割り振っています。「覚えている技」は返り値が配列のため、そのまま文字列として出力できるようにimplodeを使用しています。 

 

それでは、出力結果を確認してみましょう。

 

実行ファイル(/index.php
<?php

require_once('Class/Pikachu.php');
 
$pikachu = new Pikachu;
$pikachu->setNickname('ピカイチ');
$details = $pikachu->getDetails();

?>
 
<?php foreach($details as $key => $val): ?>
<p><?=$key?>:<?=$val?></p>
<?php endforeach; ?>

 

ピカチュウをインスタンス化(実体化)させて、「ピカイチ」というニックネームをつけました。

詳細の取得メソッド(getDetails)は配列で返ってくるため、$detailsという変数に格納してforeachで見出し($key)と一緒に取り出しています。

 

出力結果は以下の通りです。

# 出力結果
 
ピカチュウをゲットした
 
正式名称:ピカチュウ
ニックネーム:ピカイチ
現在のレベル:8
覚えている技:でんきショック,なきごえ
現在の経験値:512
レベルアップに必要な経験値:217

 

正常に取得できていますね。

一括取得のメソッドがあれば、すぐにインスタンスの中身が確認ができるため便利です。

 

 

まとめ

 

いかがだったでしょうか。

今回は「【PHP】ピカチュウから学ぶオブジェクト指向 〜トレイト編 & 経験値システム導入〜」をご紹介しました。

 

トレイト(trait)の使い方はプロジェクトによっても様々ですが、今回紹介したようにファイル内のメソッドを分割して管理するために用いることも可能です。継承する必要が無いため、複数のクラスで使いまわしするメソッド格納用として使えれば、より保守性も高まり管理手間が少なくなります。

※今回はあくまでトレイトの使い方の説明用として用いているので、それぞれのプロジェクトに合わせた使い方をしてください

 

PHPを学習中の方や、ポケモンやゲームづくりに興味がある人は、ぜひ参考にしてみてくださいね。

 

注目の記事

【PHP】可変長引数とは「点(ドット)3つ」 多次元連想配列の検索
プログラミング
PHP
【PHP】可変長引数とは「点(ドット)3つ」 多次元連想配列の検索

可変長引数とは  引数の数が決まっていない、状況に応じて複数の引数を指定したいときに、関数の引数で指定する点(ドット)3つのことです。PHP5.6以降で使用することができます。  PHPマニュアル 可変長引数リスト https://www.php.net/manual/ja/functions.arguments.php#functions.variable-arg-list ...

システムエンジニア向けまとめ情報サイト IT News Checker
ネットワーク
システムエンジニア向けまとめ情報サイト IT News Checker

新年のスタートダッシュが遅れ気味に見えるかも知れませんが、年末からじっくりと作業を進めており、やっとある程度形になりました。 師走の如く作業に走り、気分転換に雪遊びもしつつ、成人式を終えた辺りでリリースしたのが「IT News Checker」です。   IT News Checkerとは 簡潔に説明すると、まと...

ノーコード開発で将来プログラミングは不要?我々は何を学ぶべきなのか
プログラミング
amazon,AWS,Honeycode,NoCode,プログラミング学習
ノーコード開発で将来プログラミングは不要?我々は何を学ぶべきなのか

  近年、プログラミングの需要は増え勢いを増していますが、それ以上にノーコードというソースコードを打たなくでもアプリ開発ができるというソフトウェアやプラットフォームが普及してきました。 これにより一部の期待感とは別に、プログラマーという職業は今後不要になるのではないかと危機感を抱く人が出て...

たった10分!?読むだけでプログラミングが上達する3原則
プログラミング
jQuery,プログラミング学習,初心者
たった10分!?読むだけでプログラミングが上達する3原則

  プログラミングがなかなか身につかない   学習をしているけど、自分で書くとなれば思うようにいかなかったり、覚えたはずなのにその使い方や応用方法がわからない人のほとんどが、作り方そのものが間違っている傾向にあります。   今回は、プログラミング初学者や、なかなかスキルアップができない人...

進化の石編(構成) PHPポケモン 102
プログラミング
PHP,PHPポケモン,ポケモン
進化の石編(構成) PHPポケモン 102

進化の石 ピカチュウさんもそろそろ進化したがっているので、β版の公開に向けて進化の石を実装していきます。しかし、イーブイなど特別な進化先や条件を持ったポケモンを考慮すると、少し実装が手間取りそうだったので、今回は構成部分のみのまとめとなっておりますので、ご了承ください。   アイテムクラスの作...

PHPポケモン「バトルシステム編〜状態異常2〜」31
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「バトルシステム編〜状態異常2〜」31

  前回に引き続き、状態異常チェックを実装します。 まず、前回実装した「ねむり」の処理についてですが、やはりターン数をセットして経過ターン数を引いていくという処理の方が解除率もゲーム再現になるので、まず修正をしておきます。サーセン。   チェック格納トレイト(/Traits/Battle/CheckTrait.php) ...

連続の技習得編 オブジェクトをセッションへ格納 PHPポケモン57
プログラミング
PHP,PHPポケモン,ポケモン
連続の技習得編 オブジェクトをセッションへ格納 PHPポケモン57

セッション経由でのオブジェクト引き継ぎ 技習得の処理が整ってきたので、ここで連続技習得・連続レベルアップ時にも問題なく動作するように作り込んでいきます。ですが、現状のモーダルをレスポンスやメッセージと同様に、そのまま引き継いだとしてもエラーが発生します。 その原因がセッション経由でのオブジェク...

PHPポケモン(α)攻略wiki「最初のポケモン」
雑記
PHPポケモン,wiki,ポケモン
PHPポケモン(α)攻略wiki「最初のポケモン」

リリースから一ヶ月、遂にPHPポケモン(α)の攻略Wiki(仮)が公開です!   というのは大嘘で、内部の大幅変更の関係上、今回はPHPポケモンをプレイするにあたってのオススメなどをまとめて見た次第です。 ちなみに、バトルシステム自体は本家に沿って作成しているので、種族値や技性能に精通している人はブラウザ...

カテゴリ

SEO対策 イベント デザイン ネットワーク ビジネスモデル フリーランス プログラミング マーケティング ライティング 動画編集 雑記

タグ

5G Adobe AfterEffects AI ajax amazon Animate api artisan atom Automator AWS Bluetooth CSS CVR description EC-CUBE4 ECショップ ESLint Facebook feedly foreach fortify function Google Google AdSense Honeycode htaccess HTML IEEE 802.11ax Illustrator Instagram IoT JavaScript jetstream jQuery jQuery UI keyword LAN Laravel Linux MacBook MAMP meta MLM MySQL NoCode note OS OSI参照モデル Paypal Photoshop PHP phpMyAdmin PHPポケモン PremierePro rss SEO Sequel Pro Skype SNS SSH Symfony TCP/IP title Toastr Trait Twig Twitter UCC V系 WAN WebSub Wi-Fi wiki Windows WordPress XAMPP xml Xserver YouTube YouTuber Zoom アーティスト アウトプット アクセス層 アニメーション アフィリエイト イーブイ インターネット インプット エンジニア オブジェクト指向 お金配り クリック単価 クリック数 コミュニケーション能力 コロナ コンサルティング サムネイル システムエンジニア スタートアップ スタイルシート スパム データベース ディープフェイク デザイナー デザイン テレワーク ナンパ ニュース ネットワークモデル ノマドワーク バナー ピカチュウ ビジネス フィード フリーランス ブロガー ブログ プログラマー プログラミング プログラミング学習 プログラミング教育 プロトコル ホームページ制作 ポケモン マークアップ マーケティング メール リモートワーク レンダリング 三井住友 三宮 仕事依頼 児童デイ 児童発達支援 公開鍵 初心者 助成金 勉強法 営業 広告 広告収入 必勝マニュアル 放課後等デイサービス 朝活 楽天 深層学習 無線LAN 独立 神戸 福祉 秘密鍵 翻訳 自己啓発 英語 見積書 計算機 認証 読書 起業 迷惑メール 配列 銀の弾丸 集客 雑学力