プログラミング

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

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

  

まとめ

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

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

 

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

 

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

注目の記事

プログラミングを優しく解説!学んで得する3つの理由
プログラミング
プログラミング教育
プログラミングを優しく解説!学んで得する3つの理由

  プログラミング教育が始まるけど、そもそもよくわかっていない   2020年からは小学校がプログラミング学習が必修化され、翌年には中学校でも導入予定です。 しかし、保護者からすると全くわからず困惑していたり、教える先生たち教師陣からしてもよくわかっていないケースは少なくありません。   今回...

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

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

アウトプットのための3つの習慣【3対7を成立させよう】
雑記
アウトプットのための3つの習慣【3対7を成立させよう】

  インプットとアウトプットの比率は3対7がベストだと言われています。 しかし、簡単にできるインプットに比べて、アウトプットは習慣化させておくことが大切です。それができていない人の多くが、膨大に本を読んだり学習に取り組んでも身につかず、趣味のレベルで終わってしまうのです。   今回は、そんな...

【脱初心者向けプログラミング学習】処理を追え!「今、変数には何が入ってる?」
プログラミング
HTML,PHP,プログラミング学習
【脱初心者向けプログラミング学習】処理を追え!「今、変数には何が入ってる?」

  初心者から中々抜け出せない 1から処理をかけない   そんな悩みを抱えたプログラミング学習者に向けて、「脱初心者のためのプログラミング学習」についてPHPを例にまとめました。 やり方自体は同じですので、他の言語をメインとしている人は自分の環境に置き換えながら学習して、初心者から抜け出しましょ...

【Laravel7】バリデーションメッセージの日本語化【6系対応】
プログラミング
Laravel,Linux,PHP
【Laravel7】バリデーションメッセージの日本語化【6系対応】

  Laravelのバリデーションメッセージは標準だと英語で返ってきてしまいますね。 1つずつ変更する方法もありますが、言語ファイルを作成して一括変更するほうが開発時間の短縮に繋がります。   今回は「Laravel7のバリデーションメッセージを日本語化する方法」をご紹介します。Laravel6系でも同じ方法ででき...

【Laravel】1対1リレーションをわかりやすく解説(hasOne)
プログラミング
Laravel,PHP
【Laravel】1対1リレーションをわかりやすく解説(hasOne)

  Laravelの1対1リレーションのhasOneについて、公式マニュアルでは専用単語ばかりでどうしてもわかりにくいと感じてしまっている方へ向けて、わかりやすく解説しました。 ※例で紹介しているコードについては、一部英語を日本語表記で使用している部分もありますので、コピペで使用する方は必要に応じて置...

ピカチュウから学ぶオブジェクト指向 〜進化編〜 7
プログラミング
PHP,PHPポケモン,オブジェクト指向,ポケモン
ピカチュウから学ぶオブジェクト指向 〜進化編〜 7

  ※前回(第6回)で意味不明な場所に空変数が入っており、ステータスが一部しか出力できないという問題がありました。修正しています。犯人は「$stats = [];」です。(GetTrait.php)   今回はポケモンのゲームでは欠かせない、楽しみの一つとなる「進化システム」を導入していきます。これからPHPポ...

EC-CUBE4内にWordPressを設置(共存)する方法
SEO対策,プログラミング
EC-CUBE4,PHP,Symfony,Twig,WordPress
EC-CUBE4内にWordPressを設置(共存)する方法

今回使用したバージョン EC-CUBE4.0.5 WordPress5.6 ※EC-CUBE4、WordPressのカスタマイズは自己責任でお願いします。また、現在稼働中のサイトで試す際には、必ずバックアップを取ってから行なうようにしてください。   EC-CUBE4とは ネットショップを作るとなれば、様々なサービスが出回っ...

カテゴリ

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