プログラミング

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

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

  

まとめ

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

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

 

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

 

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

注目の記事

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

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

大半のネットワークビジネスが成立しない理由とは【権利収入の落とし穴】
マーケティング
MLM
大半のネットワークビジネスが成立しない理由とは【権利収入の落とし穴】

  誘われたけど、欠点が上手く説明できない 権利収入って本当にもらえるの?   ネットワークビジネスと聞けば、良い印象を抱かない人がほとんどでしょう。ですが、「何故?」と問われて説明できる人は意外にも少数派です。 そして、SNSを積極的に活用している人ならば、一度は誘いを受けたことがあるの...

ピカチュウから学ぶオブジェクト指向 〜レベルアップ編〜 5
プログラミング
PHP,PHPポケモン,オブジェクト指向,ポケモン
ピカチュウから学ぶオブジェクト指向 〜レベルアップ編〜 5

  第3回でレベルシステムを導入し、第4回では経験値システムの導入をしたので、今回はそれを合わせたレベルアップのシステムを導入します。 第1回から作成しているコードを使用しているので、もし最初から学習したい人は第1回の入門編をご覧ください。     レベルアップシステムの導入   レベル...

できるやつの「雑学力」
雑記
勉強法,雑学力
できるやつの「雑学力」

  テレビのコメンテーター、討論番組の出演者で活躍するほとんどの人は物知りだ。 あなたも「よくそんなことまで知っているな」と思ったことはあるだろう。 現代で起業して成功し続ける人のほとんどが、常に新しい情報を取り入れている。 そして得た情報に対して、歴史情報と照らし合わせ、自分なりの意見や解釈を...

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

  ピカチュウから学ぶオブジェクト指向の第2弾はオブジェクトの継承についてです。 前回作成したピカチュウクラスを使用するので、もし基礎的な内容を学習したい人は、以下の記事を参考にしてください。   オブジェクトの継承が理解できれば、複雑で規模の大きなシステムを構築することができるようになり...

引き継ぎ考慮のメッセージID重複回避編 PHPポケモン 58
プログラミング
PHP,PHPポケモン,ポケモン
引き継ぎ考慮のメッセージID重複回避編 PHPポケモン 58

今回のPHPポケモンでは内部の作り込みをしていきます。見た目への反映は無いので、プレイを楽しみにしている人や、ポケモンが好きで毎日チェックしてくれているような人は、ブラウザをバックしてもらって問題ありません。   それでは、前々回辺りから保留にしていた「メッセージIDに重複回避対策」についてです。 &...

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

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

ダメージ固定技編(ちきゅうなげ・カウンター) PHPポケモン 41
プログラミング
PHP,PHPポケモン,ポケモン
ダメージ固定技編(ちきゅうなげ・カウンター) PHPポケモン 41

ダメージ固定技とは PHPポケモンでも作成したダメージ計算機能ですが、ポケモンの技の中にはそれを必要としない技がいくつかあります。それが「固定ダメージ技」です。 ポケモンwiki(ダメージ固定技) https://wiki.ポケモン.com/wiki/ダメージ固定技 ステータスに依存せず、わざ自体にダメージ量が決...

カテゴリ

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