プログラミング

ピカチュウから学ぶオブジェクト指向 〜トレイト編〜 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を学習中の方や、ポケモンやゲームづくりに興味がある人は、ぜひ参考にしてみてくださいね。

 

注目の記事

OSI参照モデルとTCP/IP 〜ネットワークモデルとは〜【第3回 ド素人のためのネットワーク講座】
ネットワーク
OSI参照モデル,TCP/IP,ネットワークモデル,プロトコル
OSI参照モデルとTCP/IP 〜ネットワークモデルとは〜【第3回 ド素人のためのネットワーク講座】

  ド素人のためのネットワーク講座! 栄えある第3回は「ネットワークモデル」についてです。   横文字や英字が多くなってきたり、歴史的経緯が関係してきたりとややこしくなってくる部分ですが、ネットワークを理解するためには押さえておきたいポイントです。   プログラミングやシステムエンジニアとし...

戦闘用アイテム編 プラスパワー PHPポケモン96
プログラミング
PHP,PHPポケモン,ポケモン
戦闘用アイテム編 プラスパワー PHPポケモン96

戦闘用アイテムとは バトル中に使用できるアイテムはいくつかありますが、その中でも「バトル専用」のアイテムがあります。それが戦闘用アイテムであり、主にドーピングと呼ばれるものです。 アイテムカテゴリとして、プレイヤー対象(スプレーなど)、敵ポケモン対象(ボール類)、味方対象(キズぐすり)の3つに...

なぜ、お金を配るの?悪質メール・SNSを利用した詐欺的手法への対処法とは
ネットワーク
amazon,SNS,Twitter,お金配り,楽天,迷惑メール
なぜ、お金を配るの?悪質メール・SNSを利用した詐欺的手法への対処法とは

定期的に書きたくなるコラムのコーナー! 今回は、迷惑メールやSNSのDMを活用した悪質な勧誘、巷で流行っているお金配りを隠れ蓑のした巧妙な詐欺的手法などをいくつかご紹介、その対策・リクス回避の方法をまとめました。   まず結論からお伝えすると 「怪しいと思うなら手を出すな」 です。その詳細を知りたい...

ブラウザで遊べる「PHPポケモン」
プログラミング
PHP,PHPポケモン,ポケモン
ブラウザで遊べる「PHPポケモン」

PHPポケモン 約1ヶ月半をかけて作り込んできたPHPポケモンですが、ある程度遊べるぐらいのレベルになったので、みなさまにも体験・楽しんでいただけるよう本日(2020年10月12日)より一般公開します。   PHPポケモンへのリンクは本記事の最後に用意しておりますので、プレイする前に注意事項等に目を通し...

簡単に良質なブログ記事を量産する3箇条【ネタがないとは言わせない】
ライティング
ブロガー,ブログ
簡単に良質なブログ記事を量産する3箇条【ネタがないとは言わせない】

  ブログの毎日のテーマ決めが大変・・・ そもそも良質な記事をどうやって書けるようになるのかわからない   こんな悩みを抱えていませんか? 始めたばかりで伸び悩んでいる人には多いのではないでしょうか。 今回はブログで収益化や、アクセス数を伸ばそうと考えている人へ向けて「簡単に良質なブログ...

SNS拡散力アップ!PHPでOG画像付きリッチURLを自作する方法【Curl → Opengraph】
プログラミング
PHP,WordPress
SNS拡散力アップ!PHPでOG画像付きリッチURLを自作する方法【Curl → Opengraph】

  ブログやHPにサイトのURLをただ貼り付けても、どんなページなのか一目でわからないのでなかなか思うようにアクセスに繋がりません。 ですが、毎回のようにURL先の画像を準備したり、説明文を設定するのも大変ですし、ページタイトルや画像が差し替わってしまうことも考えられます。   今回はそういった手間...

今からできる!ブログのアクセスを爆UPさせる3大SNS活用法
マーケティング
Facebook,Instagram,Twitter,ブロガー,ブログ
今からできる!ブログのアクセスを爆UPさせる3大SNS活用法

  ブログを収益化させたいけど、なかなかアクセス数が増えない 記事の質は高いのに、その良さをどうやって伝えれば良いかわからない   SEO対策をする上でも、収益化するためにも記事のクオリティは重要です。 しかし、せっかく良い記事を書いていても、そのブログや記事の存在を伝えることができなけれ...

ブログで生活するための7つの道のり 〜収益化と拡散の方法教えます〜
ライティング
Facebook,Google AdSense,Twitter,ノマドワーク
ブログで生活するための7つの道のり 〜収益化と拡散の方法教えます〜

  ブログで生活したい   毎日数時間、ブログを書くだけで生きていける、そんな夢のような生活を実現させたいと思い描く人は多いですが、簡単なことでは有りません。 ですが、やらなければいけないことがわかっていれば、収益化するのは簡単です。   今回は「ブログで生活するための7つの道のり」をテ...

カテゴリ

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

タグ

5G Adobe AfterEffects AI ajax amazon Animate api artisan atom Automator AWS Bluetooth CSS CVR description EC-CUBE4 ECショップ ESLint Facebook feedly foreach function Google Google AdSense Honeycode htaccess HTML IEEE 802.11ax Illustrator Instagram IoT JavaScript jQuery jQuery UI keyword LAN Laravel Linux MacBook MAMP meta MLM MySQL NoCode note OS OSI参照モデル Paypal Photoshop PHP phpMyAdmin PHPポケモン PremierePro rss SEO 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 独立 神戸 福祉 秘密鍵 翻訳 自己啓発 英語 見積書 計算機 読書 起業 迷惑メール 配列 銀の弾丸 集客 雑学力