プログラミング

定数と静的変数 ピカチュウとイーブイで学ぶオブジェクト指向

PHP PHPポケモン イーブイ オブジェクト指向 ピカチュウ ポケモン
定数と静的変数 ピカチュウとイーブイで学ぶオブジェクト指向

PHPポケモンも順調に開発が進んでいると思いきや、ふとした気づきが自分の理解力を思い知らせることとなった今日このごろです。

プログラミングは奥が深く、しっかりと段階を追って理解を進めていけば、「これ・・・便利やんけ!」ってなることがかなり多いということがわかります。

 

それでは、かの有名な黄色いネズミさん+大人気進化先が選べる超優秀ポケモンであるイーブイさん協力のもと「PHPのオブジェクト指向」について学習していきましょう。

 

オブジェクト定数とは

現在のPHPポケモン、そして初期の「ピカチュウで学ぶオブジェクト指向」では、ポケモンが持つパラメーターなどをプロパティとして格納してきました。

ですが、そもそも「そのクラスで固定された値(定数)」というもの自体が定義できないかと考えていたところ、普通に存在しました。

 

ポケモン番号は定数

以下のようなクラスを例に見てみましょう。

<?php
// ピカチュウ
class Pikachu
{
    private $number = 25;
}

 

これが今までのPHPポケモンで実装していたピカチュウです。もちろん皆さんご存知の通り、ピカチュウの全国図鑑ナンバーは025ですね。この値は外部から書き換えられては困るため、privateprotected)のアクセス修飾子をつけて管理をしていましたが、ピカチュウのオブジェクトからでは変更出来てしまうという点を考えると、この定義自体あまり意味を成していないようにも思えます。 

<?php
// ピカチュウ
class Pikachu
{
    private $number = 25;
   
    public function __construct()
    {
        // 書き換え可能!?
        $this->number = 1000;
    }
}

 

ここで登場するのが、オブジェクト定数です。オブジェクト定数は変数ではなく固定の値を定義するものであり、ポケモンであれば図鑑ナンバーなどを設定する際に適しています。 

<?php
// ピカチュウ
class Pikachu
{
    public const NUMBER = 25;
}

 

定数の定義方法は、定数名の前にconstを付けることです。変数ではないので、ドルマークも不要です。

定数はプロパティとは異なるため、アクセス方法はアロー演算子ではなくスコープ定義演算子(::)を使ってアクセスします。

$pikachu = new Pikachu;
$pikachu::NUMBER; # 25が取得できる

 

定数の注目すべき点は、インスタンスが不要だということです。

プロパティは上記コードの1行目のようにインスタンス化(new)しなければ設定されませんが、定数はオブジェクトそのものに設定されている値のため、クラス名に対して直接アクセスが可能なのです。

Pikachu::NUMBER; # 25が取得できる

 

これにより、今までインスタンス化して取得していたポケモン番号などが直接クラス指定で取り出せるようになりました。PHPポケモンのように、DBを使わずクラス管理しているシステムにおいては大きな収穫です。

  

静的変数とは

定数はオブジェクトそのものに設定されている値だということがわかりました。ですが、中には場合によって値を変更したいものも存在しますね。そんな時には「静的変数」を使用します。

 

進化先は静的変数

進化先が複数いるポケモンの代表といえば、初代からも登場してピカブイシリーズの発売によって一気に主人公格へと進出した「イーブイ」です。

このポケモンは、初代では3種類、第2世代では追加2種類のポケモンに進化します。使用された石の種類により進化先が変更したり、現在の時間帯で進化先が変更になるため「定数」として用意するには無理がありますね。なので、ここでは静的変数を使うことで対応します。

 

今回はわかりやすさ重視で「エーフィー」と「ブラッキー」への進化分岐でクラスを作成しました。

<?php
// イーブイ
class Eievui
{
    public const NUMBER = 131;
 
    public static $evolve = '';
 
    // 現在の時間帯に合わせて進化先が変わる(金銀シリーズ)
    public function now_time($zone)
    {
        switch ($zone) {
            // エーフィーへ進化
            case '朝':
            static::$evolve = 'エーフィー';
            break;
            // ブラッキーへ進化
            case '夜':
            static::$evolve = 'ブラッキー';
            break;
        }
    }
 
}

 

静的変数の定義方法は、変数名の前にstaticをつけることです。静的変数へのアクセスは、constと同じようにスコープ定義演算子(::)を使い、インスタンス化しなくてもその値へアクセスすることが可能です。

通常時は決まった進化先を持っておらず、now_timeのメソッドが呼び出された際に、そのときの時間帯に合わせて値を変更しています。

そしてプロパティとの大きな違いは、値をインスタンス自身が保有しているわけではないという点です。

$eievui1 = new Eievui;
$eievui2 = new Eievui;
 
$eievui1->now_time('朝');
$eievui2->now_time('夜');

 

先程作成したイーブイをインスタンス化、それぞれに朝と夜の時間帯をセットしました。今までのPHPポケモンで行なっていたプロパティの書き換えであれば、$eievui1の進化先には「エーフィー」$eievui2の進化先には「ブラッキー」がセットされているはずですね。

しかし、結果は以下のようになります。

$eievui1::$evolve; # ブラッキー
$eievui2::$evolve; # ブラッキー

 

静的変数はあくまで、オブジェクトに対して設定されているため、それぞれのインスタンスに対して値は格納されていません

  

もちろん、PHPファイルそのものが書き換わるわけではないので、次のページを読み込むことで進化先は空に戻ります

 

この静的変数を上手く使えば、PHPポケモンの「へんしん」などの技を使用した際に書き換えを懸念していたステータスなどを、静的変数として定義して書き換えることで上手く活用することができそうです。

  

親と子の関係

もし定数や静的変数が「親」と「子」それぞれに設定されていれば、どのようにしてアクセスができるのかを確認してみましょう。

PHPポケモンでもおなじみ、ピカチュウのクラスの親として「Pokemon」を読み込ませましょう。

<?php
# 親クラス(ポケモン)
abstract class Pokemon
{
    public const NUMBER = 0;
}
 
# 子クラス(ピカチュウ)
class Pikachu extends Pokemon
{
    public const NUMBER = 25;
}

 

ピカチュウに親クラスをセットして、それぞれに図鑑ナンバーを持たせました。この図鑑ナンバーをそれぞれのクラスから取り出す方法を見ていきます。

 

staticは誰のもの?

まずはアクセス方法の1つ「static」を使います。これはイーブイのクラスでも使用していましたが、静的変数などオブジェクトそのものが持っている値に対してアクセスする際に使用していましたね。これを、それぞれのクラス内で呼び出してみましょう。

<?php
# 親クラス(ポケモン)
abstract class Pokemon
{
    public const NUMBER = 0;
 
    public function __construct()
    {
        echo 'Pokemon:'.static::NUMBER;
    }
}
 
# 子クラス(ピカチュウ)
class Pikachu extends Pokemon
{
    public const NUMBER = 25;
   
    public function __destruct()
    {
        echo 'Pikachu:'.static::NUMBER;
    }
}
 
new Pikachu;

 

両方をconstructにすると子クラスが優先されてしまうので、親(Pokemon)はconstruct、子(Pikachu)ではdestructを使い、staticでNUMBERの定数にアクセスしてみました。

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

Pokemon:25
Pikachu:25

 

new Pikachuでインスタンス化したオブジェクト内でstaticを使ったアクセスをすると、どちらも「Pikachu」に対してアクセスをしているようですね

これで、親クラスで全ポケモンにそれぞれが持ったオブジェクト定数や静的変数にアクセスしたい場合は、staticを使えば良いということがわかりました。

 

では、もし子である「Pikachu」がNUMBERの定数を持っていなければどうでしょうか?

<?php
# 親クラス(ポケモン)
abstract class Pokemon
{
    public const NUMBER = 0;
 
    public function __construct()
    {
        echo 'Pokemon:'.static::NUMBER;
    }
}

 子クラス(ピカチュウ)
class Pikachu extends Pokemon
{
    public function __destruct()
    {
        echo 'Pikachu:'.static::NUMBER;
    }  
}
 
new Pikachu;

 

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

Pokemon:0
Pikachu:0

 

ピカチュウにはNUMBERの定数が設定されていませんが、親クラスには設定されているため、ピカチュウクラス内でstaticを使ってもエラーは出ず呼び出すことができました。

もしデフォルトとしてポケモン自体に値が決まっており、ポケモンによっては上書きして値を持たせる場合に、この仕組みは使えそうですね。

 

では、逆のパターン(親に番号なし・子に番号有り)ではいかがでしょうか?

<?php
# 親クラス(ポケモン)
abstract class Pokemon
{
    public function __construct()
    {
        echo 'Pokemon:'.static::NUMBER;
    }
}
 
# 子クラス(ピカチュウ)
class Pikachu extends Pokemon
{  
    public const NUMBER = 25;
   
    public function __destruct()
    {
        echo 'Pikachu:'.static::NUMBER;
    }
}
 
new Pikachu;

 

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

Pokemon:25
Pikachu:25

 

両方が設定されている際にも親から子の定数にはアクセスが出来ていたので、これは予想通りの結果と言えるでしょう。

このように呼び出しの元がピカチュウであれば、staticではピカチュウを優先的に参照してくれるということがわかりました。

 

selfは誰のもの?

staticとよく一緒に取り上げられるものに「self」があります。こちらもstaticと同様に定数や静的変数にアクセスする際に用いられます。

 

まずは親子共に番号が設定されている場合の参照先を見てみましょう。

<?php
# 親クラス(ポケモン)
abstract class Pokemon
{
    public const NUMBER = 0;
 
    public function __construct()
    {
        echo 'Pokemon:'.self::NUMBER;
    }
}
 
# 子クラス(ピカチュウ)
class Pikachu extends Pokemon
{
    public const NUMBER = 25;
   
    public function __destruct()
    {
        echo 'Pikachu:'.self::NUMBER;
    }  
}
 
new Pikachu;

 

staticではなく、selfでそれぞれのクラス内からNUMBERへアクセスしました。出力結果は以下の通りです。

Pokemon:0
Pikachu:25

 

それぞれ呼び出された場所に設定された番号を取ってきていますね。これなら、それぞれに定数や静的変数が設定されていても、staticselfを使い分けることで好きな方を選び取得することができそうです。

 

では、staticと同様に親子どちらかだけに設定されている場合の取得結果を見てみましょう。

まずは、親のみに番号が設定されている場合です。

<?php
# 親クラス(ポケモン)
abstract class Pokemon
{
    public const NUMBER = 0;
 
    public function __construct()
    {
        echo 'Pokemon:'.self::NUMBER;
    }
}
 
# 子クラス(ピカチュウ)
class Pikachu extends Pokemon
{
    public function __destruct()
    {
        echo 'Pikachu:'.self::NUMBER;
    }
}
 
new Pikachu;

 

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

Pokemon:0
Pikachu:0

 

staticと同様に、子に設定されていなければ親の値を参照してきてくれました。ピカチュウはピカチュウである前に「ポケモン」だということでしょう。 

では、逆のパターン(親に設定無し・子に設定有り)で見てみましょう。

<?php
# 親クラス(ポケモン)
abstract class Pokemon
{
    public function __construct()
    {
        echo 'Pokemon:'.self::NUMBER;
    }
}
 
# 子クラス(ピカチュウ)
class Pikachu extends Pokemon
{
    public const NUMBER = 25;
   
    public function __destruct()
    {
        echo 'Pikachu:'.self::NUMBER;
    }
}
 
new Pikachu;

 

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

PHP Fatal error:  Uncaught Error: Undefined class constant 'NUMBER' in /※※※※.php:7

 

こちらはstaticと異なり、エラーが吐き出されました。7行目でのエラーなので、親クラスであるPokemonself::NUMBERに対してアクセスしようとしたのが原因です。

PokemonクラスにはNUMBERの定数または静的変数がセットされていません。staticでは呼び出し元であるPikachuの番号を参照していましたが、selfでは自身そのものを指しています。これなら、両方が設定されていたときにそれぞれに設定されていた番号が取得できていたことにも納得です。

 

selfstaticは、同じようで違うということがわかりました。インスタンス自身(呼び出し元)を指す際にはstatic、クラス(オブジェクト)そのものを指す場合にはselfを使うのが正しいということですね。

  

まとめ

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

今回は「定数と静的変数」について、ピカチュウとイーブイを使ってその動きをご紹介しました。

 

言葉だけでは説明や理解が難しく、オブジェクト指向における大きなハードルとも言える部分ですが、実際に馴染みあるものを想定して試してみると理解がしやすいでしょう。自分の場合は、ポケモンという存在がより理解に適していました。

 

プログラミング学習に取り組んでいる方や、オブジェクト指向で苦戦している方は、ぜひ参考にしてみてくださいね。

注目の記事

PHPポケモン「状態異常+逃走編〜ねむり・こおり・やけど・どく〜」24
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「状態異常+逃走編〜ねむり・こおり・やけど・どく〜」24

状態異常の実装  今回は、前回作成した「まひ」を参考に、「ひんし」を除いた残りの状態異常も実装していきます。    クラスの作成  まずはそれぞれのクラスを作成します。前回解除時のメッセージを設定出来ていなかったので、まひと合わせて実装していきましょう。   状態異常:やけど(...

ポケモン預かりシステム編 システムの実装 PHPポケモン 87
プログラミング
PHP,PHPポケモン,ポケモン
ポケモン預かりシステム編 システムの実装 PHPポケモン 87

ポケモン預かりシステムの実装 システムの仕様とクラスも整ってきたので、いざ実装をしていきましょう。 前回までに作成した項目で、いくつか変更になったものがあるので、まずはじめに挙げておきます。   シャットダウン機能 ボックスの選択を解除するというものでしたが、こちらを不採用にしました。ボックスは...

オブジェクト指向有効活用編 PHPポケモン 93
プログラミング
PHP,PHPポケモン,ポケモン
オブジェクト指向有効活用編 PHPポケモン 93

オブジェクト指向の有効活用 β版に向けたPHPポケモンの構成見直し、今回は「オブジェクト指向」の役割について、より理解を深めつつ、保守性も良くなるように整えていきます。   機能を持たせる 様々なプロパティを定数や静的変数へ以降していますが、今回は「静的メソッド」の活用範囲を増やしていきます。まず...

PHPポケモン「わざ編〜チャージ技の実装〜」34
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「わざ編〜チャージ技の実装〜」34

チャージ技とは ポケモンの技は数多く存在していて、その中でも特別な処理が必要なものがいくつかあります。その1つが「チャージ技」です。 ※チャージ技とはポケモン上で用いられている用語ではありません   現在実装している初代御三家+ピカチュウの初代レベルアップ技の中では以下の2つがあります。 ロ...

初心者必見!仕事がデキる人のIllustrator活用術3選
デザイン
Adobe,Illustrator,サムネイル
初心者必見!仕事がデキる人のIllustrator活用術3選

  仕事の速い人の大半は、「効率の良い方法」や「便利な使い方」を知っていて使いこなしています。これは、デザインの現場でも同じです。 今回はその中でもIllustratorで知っておくと便利な機能を3つご紹介します。この3つを押さえておくだけで、作業効率は格段にアップするので、これからソフトの使い方を覚...

PHPポケモン「引数メソッド実行編」デモ有り(御三家の追加)11
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「引数メソッド実行編」デモ有り(御三家の追加)11

  前回のPHPポケモンではメソッドを外部から実行できるようにコントローラー(インターフェース)を作成しました。なので、今回は引数が必要となるメソッドの実装に挑戦してみましょう。 最後にはデモページを準備しているので、気になった人はぜひ遊んでみてください。   第1回はコチラ     ...

Laravel8 Jetstream fortifyを活用したマルチログイン実装方法
プログラミング
fortify,jetstream,Laravel,PHP,認証
Laravel8 Jetstream fortifyを活用したマルチログイン実装方法

はじめに Laravel8からは、今までの認証機能がなくなり公式より「Jetstream推奨」と言われるようになりました。単純なログイン機能だけを使いたいのであれば、ライブラリをインストールしてコンパイルするだけで、ほとんどの機能はもちろん、レイアウトもそれなりに使える状態になっているという優れものです。 ...

経験値分配編 PHPポケモン 89
プログラミング
PHP,PHPポケモン,ポケモン
経験値分配編 PHPポケモン 89

経験値の分配とは 大型アップデート後、最初の追加機能は「経験値の分配」についてです。 ポケモンの入れ替えができるようになりましたが、経験値をもらえるのは現在フィニッシャーのみとなっており、レベルの低いポケモンを育てるのが困難な状態です。なので、ゲームバランスを整えるためにも、まず経験値周りの処...

カテゴリ

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 独立 神戸 福祉 秘密鍵 翻訳 自己啓発 英語 見積書 計算機 認証 読書 起業 迷惑メール 配列 銀の弾丸 集客 雑学力