プログラミング

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

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を使うのが正しいということですね。

  

まとめ

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

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

 

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

 

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

注目の記事

AIが人類にもたらす驚異!深層学習が与える影響とは
ネットワーク
AI,ディープフェイク,深層学習
AIが人類にもたらす驚異!深層学習が与える影響とは

  海外の記事でAIについて記述した興味深いものが掲載されました。   今回は「AIが人類にもたらす驚異!深層学習が与える影響とは」について、上記サイトを参考にまとめましたのでご紹介します。 ※直訳ではありません、あくまで記事の内容を参考にして自らの考えを記述したものです     AIの驚異と...

反動技編(はかいこうせん・とびひざげり)PHPポケモン40
プログラミング
PHP,PHPポケモン,ポケモン
反動技編(はかいこうせん・とびひざげり)PHPポケモン40

反動技とは ポケモンでは反動技というものがあります。反動によっても様々で、現在の仕組みのままでも実装可能なものや、新たに処理が必要なものまであります。なので、一律で反動技という同じ処理は出来ません。  反動技(ポケモンwiki) https://wiki.ポケモン.com/wiki/反動技 反動技(はんどうわざ...

LANとWANについて【第2回 ド素人のためのネットワーク講座】
ネットワーク
IoT,LAN,WAN,Wi-Fi
LANとWANについて【第2回 ド素人のためのネットワーク講座】

  YQUALがお送りする、ド素人のためのネットワーク講座。 栄えある第2回は「LANとWANについて」です。   フロントエンジニアや現在プログラミングを学習中の方を中心に、ネットワークについての基礎的理解を深めていくための内容になっています。 ざっくりとした説明で物足りない、または細かく見ていった...

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

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

バトル状態のクラス化編 PHPポケモン 67
プログラミング
PHP,PHPポケモン,ポケモン
バトル状態のクラス化編 PHPポケモン 67

バトルの状態 PHPポケモンでも様々な技を再現してきましたが、まだまだ未実装のものはたくさんあります。そのほとんどがイレギュラー処理の必要なものだったりします。 それらをしっかりと解決していくためにも、今回は「バトル状態」をひとまとめに管理できるようにシステムの見直しを行います。   ひとまとめに...

HTMLの基本設計「よくわかるSEO対策」構造化(マークアップ)編
SEO対策
HTML,SEO,マークアップ
HTMLの基本設計「よくわかるSEO対策」構造化(マークアップ)編

  HTML5がリリースされて随分経ちました。 それにより多くのタグが増え、それにより今までデザインを目的と使用されていたものが「構造化」という本来の役割を持たされるようになりました。    構造化は、目に見えにくい部分です   それぞれの役割を理解していなければ、せっかくきれいなサ...

PHPポケモン「状態異常編〜まひ〜」23
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「状態異常編〜まひ〜」23

  今回のPHPポケモンでは「状態異常」を導入します。バトルシステムにも関係してくる部分ですが、それ以外にも影響を与える部分が多く、且つ非常に判定がややこしく、作り込む必要があったため1つずつ片付けていきます。   状態異常の実装  ポケモンの除隊異常に該当するものは以下の7通りです。 ...

そらをとぶ&あなをほる編 PHPポケモン46
プログラミング
PHP,PHPポケモン,ポケモン
そらをとぶ&あなをほる編 PHPポケモン46

チャージ中の回避技 以前は「ロケットずつき」や「ソーラービーム」をサンプルとしてチャージ技を実装しましたが、今回は少し特別な効果をもったチャージ技を実装します。それが「そらをとぶ」と「あなをほる」です。これらは初代ポケモンでも重宝される技であり、チャージ中に相手からの攻撃を回避することができま...

カテゴリ

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