プログラミング

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

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

  

まとめ

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

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

 

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

 

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

注目の記事

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

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

WordPressのJSファイル読み込みで覚えておきたい便利ワザを2つ紹介します
プログラミング
jQuery,PHP,WordPress
WordPressのJSファイル読み込みで覚えておきたい便利ワザを2つ紹介します

  JSファイルを読み込むときに、deferやasyncを付与したい・・・ get_template_directory_uri()をJSファイル内で使用したい・・・   WordPressには便利な関数が沢山用意されていますが、その全てが万能だということはありません。 今回はSEO対策でも必要になるdeferやasyncをスクリプトタグに付与させる...

プログラミングとは?現役システムエンジニアが教える裏事情
プログラミング
システムエンジニア,プログラマー
プログラミングとは?現役システムエンジニアが教える裏事情

  プログラミングってよくわからない? 実際に何をやっているの?   最近注目されているSE(システムエンジニア)やPG(プログラマー)という職業ですが、「そもそもプログラミングとは?」といった疑問を抱えている方も多いですね。 今回は、そういった方へ向けて「プログラミングの基礎知識と裏事情」...

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

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

バズる!ビジネスの見つけ方 〜何で起業するか悩んでいませんか?〜
マーケティング
ビジネス,起業
バズる!ビジネスの見つけ方 〜何で起業するか悩んでいませんか?〜

  独立や起業を志している9割以上の人が「何をビジネスにするか?」を悩んでいます しかし、それは負のサイクルです。 起業するためにビジネスを考えるという行為自体が”矛盾している”ということに気づかなければ、このサイクルからは抜け出すことができません。 その結果、行動できずに終わってしまう人は多...

PHPポケモン「バトルシステム編〜HP計算〜」26
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「バトルシステム編〜HP計算〜」26

HP計算 これまでに実装したダメージ計算ですが、計算はできていてもお互いに相手ポケモンのHPを削ることはできませんでした。なので、今回は実際のバトルのように、HPに対してダメージを与えるという仕組みを作成していきます。   残りHP ここで必要になるのが「残りHP」という概念です。今までステータス上のHP...

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

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

動画編集で知っておくべき基本的な3工程
動画編集
Adobe,AfterEffects,Illustrator,Photoshop,PremierePro
動画編集で知っておくべき基本的な3工程

  YouTubeに動画を投稿したいけど、動画の基本的な作成手順がわからない・・・   動画作成をするためのソフトは色々ありますが、有料なものであればやはりAdobe製品に軍配が上がります。 しかし準備したは良いものの、いろんなソフトが合ってどれを使えばよいか分からないという悩みを抱えている方は非常...

カテゴリ

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