プログラミング

ピカチュウから学ぶオブジェクト指向 〜入門編〜 1

PHP PHPポケモン オブジェクト指向 ポケモン
ピカチュウから学ぶオブジェクト指向 〜入門編〜 1

オブジェクト指向とは 

オブジェクト指向プログラミングとは、互いに密接な関連性を持つデータとメソッドをひとつにまとめてオブジェクトとし、それぞれ異なる性質と役割を持たせたオブジェクトの様々な定義と、それらオブジェクトを相互に作用させる様々なプロセスの設定を通して、プログラム全体を構築するソフトウェア開発手法である。

 

上記引用文で「なるほど!わかった!」となった方は、本記事を読む必要はありません

 

プログラミング、特にオブジェクト指向の説明になれば専門用語がかなり多く出てくるため、初心者がただ読んだだけでは理解できないケースがほとんどです。

今回はそんなオブジェクト指向について、よりわかりやすく理解を深め「便利じゃん!」となるように、日本の代表的ゲームである「ポケモン」のピカチュウの力を借りてご説明します。もしポケモンのゲームをやったことがない、全く知らないという人は、ブラウザをバックして別のオブジェクト指向について説明が書かれている記事を参考にするか、一度初代ポケモンをプレイしてから出直してください。

  

ピカチュウを作る 

オブジェクト指向では、まずクラスを作成することから始まります。今回はピカチュウをという存在を定義するために、Pikachuというクラスを作成します。 

<?php
// ピカチュウ
class Pikachu
{
   
}

 

これでピカチュウが出来上がりました。中身は空っぽですので、これから1つずつ理解しながら詰め込んでいきます。

 

オブジェクト指向では、まずこのようにクラスを作ることで、ピカチュウという存在そのものを定義します。ゲームを進めていく中で、ピカチュウは1匹だけではありませんよね(ややこしいのでピカチュウ版は除きます)。好きな人は、2匹、3匹と捕まえるかも知れません。さらに、技構成全く同じではなかったり、能力値やレベルも個体によってばらつきが出ます。

しかし中身が違っていても、その全てが「ピカチュウ」で有ることには代わりありません。その「ピカチュウ」という存在事態を定義するのがクラスなのです。

  

個体を作成(インスタンス)

 クラスを作成しても、それは「ピカチュウ」という存在事態が定義されたに過ぎず、実体はありません。これは初期の「ミュウ」という存在で考えてみるとわかりやすいかも知れません。

初代のポケモンが発売された当初、「ミュウ」という存在自体は確かにありました。しかし、ゲーム上で捕まえることが出来ず(バク・裏技を除く)、実体はどこにも有りませんでした。しかし、イベントで配布するということによって、初めてその実体が確認され、ユーザーの元に届き、ミュウを使うことができるようになりました。この実体こそが「インスタンス」です。

 

それでは、ピカチュウの実体(インスタンス)を作ってみましょう。

<?php
// ピカチュウ
class Pikachu
{
   
}

$pikachu = new Pikachu;

 

new クラス名」とすることで、ピカチュウのインスタンスを作成することができます。$pikachuという変数に代入しているので、$pikachuはピカチュウです。もちろんピカチュウは1匹限りの存在ではないので、複数匹呼び出すことが出来ます。 

<?php
// ピカチュウ
class Pikachu
{
   
}

// トキワの森
$pikachu1 = new Pikachu;
$pikachu2 = new Pikachu;
$pikachu3 = new Pikachu;
$pikachu4 = new Pikachu;
$pikachu5 = new Pikachu;

 

$pikachu15までの5匹分のインスタンスを作成しました。この全てがピカチュウですが、それぞれは別個体です。もし$pikachu1に10万ボルトという技を覚えさせたとしても、それに連動して$pikachu23も同じように覚えることはありません。

 

名前の設定(プロパティ)

 では、ピカチュウのクラスに情報を入れていきましょう。

まず最初に必要になるのは名前です。正式名称として、ピカチュウという名前をクラス内に設定しましょう。 

<?php
// ピカチュウ
class Pikachu
{
    public $name = 'ピカチュウ';
}

$pikachu = new Pikachu;
echo $pikachu->name;

 

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

ピカチュウ

 

期待した通りの結果が出力されましたね。

それでは、クラス内に追加した部分を見みましょう。

public $name = 'ピカチュウ';

 

クラス内では変数が定義できます。これをプロパティ呼びます。ここに値を代入することで、ピカチュウのクラス内では$name($this->name)をピカチュウとして扱うことが出来ます。

※クラス内の$nameの手前に付けたpublicについては後ほど解説します

 

インスタンス化(実体化)したピカチュウから名前を教えてもらうためには、クラス内に定義したプロパティにアクセスする必要があります。

$pikachu = new Pikachu;
echo $pikachu->name;

 

ピカチュウというインスタンスが格納されている$pikachuから、->を使用してnameを取り出しています。こうしておけば、インスタンスさえ呼び出されていれば、いつでも名前を確認することが可能です。

 

ニックネームをつける(コンストラクタ)

 ポケモンは捕まえた際に、ニックネームを付けることができます。同じポケモンを複数体育てるのであれば、その判別のためにもニックネームがなければひと目で見分けが付きません。今回はポケモンを捕まえる過程が無いので、インスタンスを作成した時点でニックネームを設定できる仕様にしましょう。そのために使うのがコンストラクタです。

<?php
// ピカチュウ
class Pikachu
{
   
    public $name = 'ピカチュウ';
    public $nickname;
    
    public function __construct($nickname=null)
    {
        if(is_null($nickname)){
            $this->nickname = $this->name;
        }else{
            $this->nickname = $nickname;
        }
    }
  
}
 
$pikachu = new Pikachu('ピカイチ');
echo $pikachu->nickname;

 

echo $pikachu->nicknameの出力結果は以下の通りです。

ピカイチ

 

クラスの使い方に慣れていない方は、そろそろややこしくなってきましたね。でも安心してください。1行ずつしっかり理解していけば問題有りません。

 

まず、クラス内にニックネームを格納するためのプロパティを準備しました。

public $nickname;

 

初期状態ではニックネームは設定されていないので、プロパティだけを宣言します。そして、次に出てきている関数が今回の注目ポイントです。

public function __construct($nickname=null)

 

クラス内で使える変数(プロパティ)があるように、クラス内で使える関数もあります。これをメソッドと言います。メソッドについては次項で詳しく解説します。

今回クラス内で使っている__constructは特別なものです。なぜなら、このクラスをインスタンス化(実体化)した際、自動的に動いてくれるからです。クラスの呼び出し部分から動きを確認してみましょう。

$pikachu = new Pikachu('ピカイチ');

 

先程の呼び出し方と少し変わって、new Pikachuのあとにカッコと値がありますね。これは引数です。ピカチュウというクラスを呼び出す際に、第1引数として「ピカイチ」という値を指定しました。

クラスが呼び出されると、先程説明したようにクラス内にある__constructが自動で動きます。第1引数で指定された「ピカイチ」という値は、ここで受け取ることができます

__constructの引数として、$nickname=nullが指定されています。これも関数の引数と同じで、もしクラスを呼び出す際にニックネームの指定がなければ、nullを初期値として格納します。今回は「ピカイチ」という値が指定されているので、$nicknameにはピカイチが格納されました

では、__constructの中身を確認してみましょう。

if(is_null($nickname)){
    $this->nickname = $this->name;
}else{
    $this->nickname = $nickname;
}

 

ここで1つ複雑なポイントを解消しておきましょう。

__constructで引数で受け取る値を格納する変数を$nicknameとしました。しかし、クラス内ではプロパティとして同じように$nicknameが宣言されています。これは名称が同じであっても、同じものではありません。なぜなら、クラス内で定義したプロパティは、$nicknameとしては使用せずに、$this->nicknameというように使用するからです。

 

$thisはクラスのことを指しています。今回であればPikachuというクラスです。クラス内のプロパティである$name$nicknameにアクセスする場合は$this->name$this->nicknameとしなければなりません。そのため、__construct内の$nicknameは別物なのです。更にこの引数として受け取った$nicknameは、プロパティと違って__construct内でしか使用できません

 

上記を踏まえて、先程の処理を1行ずつ確認見ていきましょう。

if(is_null($nickname)){

 

引数で受け取った$nickname(ピカイチ)をis_nullで判定して条件分岐(if)しています。今回はピカイチという値が引数で指定され、$nicknameに格納されているので、is_nullfalse(否)となり、else内の処理に入ります。

}else{
    $this->nickname = $nickname;
}

 

else内では$this->nickname$nicknameを代入しています。$this->nicknameはピカチュウクラスのプロパティです。初期値が設定されていないため、現在は何も格納されていません。そこに代入する$nicknameには引数で受け取った「ピカイチ」が格納されています。$this->nickname(空)に$nickname(ピカイチ)を代入することで、nicknameというプロパティに「ピカイチ」という値をセットしているのです。

 

上記の処理がクラスを呼び出した時点「$pikachu = new Pikachu(‘ピカイチ‘);」で行われています。そのため、インスタンス化(実体化)した$pikachuからニックネームを取り出すと、ピカイチという値が取得できるのです。

echo $pikachu->nickname;
# 出力結果
ピカイチ

 

では、クラスを呼び出す際に引数を指定しなかった場合を見てみましょう。

<?php
// ピカチュウ
class Pikachu
{
   
    public $name = 'ピカチュウ'; #
    public $nickname;
    
    public function __construct($nickname=null)
    {
        if(is_null($nickname)){
            $this->nickname = $this->name;
        }else{
            $this->nickname = $nickname;
        }
    }
  
}
 
$pikachu = new Pikachu;
echo $pikachu->nickname;
# 出力結果
ピカチュウ

 

これは、__construct内のif文でis_null($nickname)true(正)を返したからです。

if(is_null($nickname)){
    $this->nickname = $this->name;

 

is_null内の$nicknameは引数の値が格納されていましたね。指定されていなければ初期値「$nickname=null」として設定されたnullが入っているので、if文内の「$this->nickname = $this->name」が実行されます。

nicknameのプロパティに、nameのプロパティ(ピカチュウ)がセットされています。ポケモンのゲームでもニックネームを指定しなければポケモンの正式名称がセットされるので、仕様としては同じになりました。

 

このように、__constructはクラスを呼び出したとき、最初に自動的に実行されるメソッド(関数)だということです。合わせて、プロパティと変数との違い($this->nickname$nickname)についても、ざっくりで構いませんので覚えておきましょう。

 

最後に__construct内をPHP7仕様に簡略化しておきます。

※処理内容はほとんど変わりませんので、is_nullを使った方法の方がわかりやすい人はそちらを参考にしてください。null合体演算子の場合は空文字(”)を許可してしまいますが、今回はそこまで厳密にしていしないものとします

<?php
// ピカチュウ
class Pikachu
{
   
    public $name = 'ピカチュウ';
    public $nickname;
    
    public function __construct($nickname=null)
    {
        $this->nickname = $nickname ?? $this->name;
    }

}

 

null合体演算子について内容を詳しく知りたい人は、以下の記事を参考にしてください。

【PHP7】はてな2つとは??Null合体演算子を使った存在チェック 【PHP7】はてな2つとは??Null合体演算子を使った存在チェック

  PHP Notice:  Undefined variable: 変数名 in /***/***.php on line 2   PHPで変数や対象のキーが存在しない配列を使おうとすれば、上記のようなエラーが吐き出されますね。PHP5.6までは初期値を設定したり、issetで判定したりしてそれを回避していましたが、2015年末にリリースされたPHP7からは新しくN...

 

技を取得(メソッド)

 ポケモンといえば技を習得できますね。初代ピカチュウの場合、最初は「でんきショック」と「なきごえ」という技を覚えています。これはピカチュウという存在事態に共通していることなので、クラスへ設定します。

private $move = [
    'でんきショック',
    'なきごえ',
];

 

今回はpublicではなくprivateでプロパティを準備しました。こちらも後ほど解説します。

 

次に、技の一覧を取得するために、クラス内で使用できる関数(メソッド)を作成します。

// 覚えている技の一覧を取得する
public function getMove()
{
    return $this->move;
}

 

__constructは特別なメソッドでしたが、自ら用途に合わせて使いたい関数をクラス内に準備することができます。これがメソッドです。

PHPでは変数や関数を必要に応じて作ることができますよね。これを、そのクラス内で使う用として準備するものがメソッドになります。

 

では、技を増設した処理と出力結果を確認してみましょう。

<?php
// ピカチュウ
class Pikachu
{
   
    public $name = 'ピカチュウ';
    public $nickname;
    private $move = [
        'でんきショック',
        'なきごえ',
    ];
 
    // クラス呼び出し時(インスタンス作成時)に自動で最初に実行される処理
    public function __construct($nickname=null)
    {
        $this->nickname = $nickname ?? $this->name;
    }
 
    // 覚えている技の一覧を取得する
    public function getMove()
    {
        return $this->move;
    }
  
}

$pikachu = new Pikachu;
var_export($pikachu->getMove());
# 出力結果
array (
  0 => 'でんきショック',
  1 => 'なきごえ',
)

 

ピカチュウの技一覧が取得できましたね。では、今回追加したgeMoveというメソッドを確認してみましょう。

// 覚えている技の一覧を取得する
public function getMove()
{
    return $this->move;
}

 

内容はいたって簡単です。getMoveを呼び出せば、技の一覧を返す「retrun $this->move」という内容です。$this->moveには「でんきショック」と「なきごえ」を配列として入れているので、それを返却してくれています。

 

メソッドの呼び出し方法も、プロパティと同じように->を使用します。

$pikachu->getMove()

 

インスタンスが作成されていれば、そのクラス内で準備しているメソッドを呼び出すことができるのです。

 

アクセス修飾子

 それでは気になっていたpublicprivateについて、最後にまとめておきましょう。

プロパティやメソッドの手前についていたこれらは、アクセス修飾子と言います。PHPでは以下の3種類が用意されています。

  • public
    クラス内、クラス外のどこからでもアクセスが可能
  • protected
    同じクラス及び子クラスからアクセスが可能
  • private
    同じクラス内からのみアクセスが可能

※protectedについては今回無視しましょう。混乱しないためにも、まずはpublicとprivateを押さえて置けば十分です。

 

publicは、どこからでもアクセスが可能なプロパティ、メソッドだということを宣言します。例えば、$pikachu->nameでピカチュウという値が取得できるのもpublic $nameと宣言しているおかげです。

それに対して、先程$moveprivateと宣言しました。その結果、nameとは違い$pikachu->moveでは取得することができません。

<?php

// ピカチュウ
class Pikachu
{
    public $name = 'ピカチュウ';
    public $nickname;
    private $move = [
        'でんきショック',
        'なきごえ',
    ];

    // クラス呼び出し時(インスタンス作成時)に自動で最初に実行される処理
    public function __construct($nickname=null)
    {
        $this->nickname = $nickname ?? $this->name;
    }
 
    // 覚えている技の一覧を取得する
    protected function getMove()
    {
        return $this->move;
    }
  
}
 
$pikachu = new Pikachu;
$pikachu->move;
# 出力結果
PHP Fatal error:  Uncaught Error: Cannot access protected property Pikachu::$move in ...

 

これでは困るため、技の一覧を取得するためのgetMoveというメソッドを作成したのです。

 

しかし、ここで1つ疑問が残ります

結局取得できるようにするのであれば、privateではなくpublicで良いのでは?

 

そう思いますよね。

しかし、それではいけません。なぜなら、アクセスができるということは、取得だけではなく「書き込み」も出来てしまうからです。

<?php
# moveのアクセス修飾子をpublicに変更した場合

// ピカチュウ
class Pikachu
{
    public $move = [
        'でんきショック',
        'なきごえ',
    ];
 
    // 覚えている技の一覧を取得する
    public function getMove()
    {
        return $this->move;
    }
  
}
 
$pikachu = new Pikachu;
$pikachu->move = [
    'かえんほうしゃ',
    'ハサミギロチン',
];
var_export($pikachu->getMove());
# 出力結果
array (
  0 => 'かえんほうしゃ',
  1 => 'ハサミギロチン',
)

 

 

 

このように、簡単に外部から書き込みが出来てしまうことはエラーや予期せぬ結果を招く危険性があります。そうならないためにも、アクセス修飾子を使って制御する必要があります。

 

これを踏まえて、他のアクセス修飾子も見直したクラスがこちらです。

<?php
// ピカチュウ
class Pikachu
{
   
    private $name = 'ピカチュウ';
    public $nickname;
    private $move = [
        'でんきショック',
        'なきごえ',
    ];
 
    // クラス呼び出し時(インスタンス作成時)に自動で最初に実行される処理
    public function __construct($nickname=null)
    {
        $this->nickname = $nickname ?? $this->name;
    }
 
    // 正式名称を取得する
    public function getName()
    {
        return $this->name;
    }
 
    // 覚えている技の一覧を取得する
    public function getMove()
    {
        return $this->move;
    }
  
}

 

ニックネーム(nickname)は変わってしまっても大きく支障がありませんので、publicのままにしていますが、正式名称(name)は変えられると一大事ですのでprivateへ変更しました。取得出来ないままでも困るので、技と同様にgetNameというメソッドで取得できるようにしています。__constructはpublicしか指定できませんので、変更は不要です。

 

このように、外部から書き込みしても良いか、呼び出しが出来ても良いかなどを考えながらアクセス修飾子を設定していきます。

 

まとめ

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

今回は「【PHP】ピカチュウから学ぶオブジェクト指向 〜入門編〜」をご紹介しました。

今回取り上げたピカチュウのように、決まった存在を定義する際にはクラスを使うと管理がしやすくなり、開発がスムーズになります。

オブジェクト指向への理解がまだまだ甘いこれからPHPを本格的に学習しようと考えている方は、ぜひ参考にしてくださいね。

 

第2回はコチラ(クラス継承編)
ピカチュウから学ぶオブジェクト指向 〜クラス継承編〜 2 ピカチュウから学ぶオブジェクト指向 〜クラス継承編〜 2

  ピカチュウから学ぶオブジェクト指向の第2弾はオブジェクトの継承についてです。 前回作成したピカチュウクラスを使用するので、もし基礎的な内容を学習したい人は、以下の記事を参考にしてください。 [shortcode_url_og url="https://s-yqual.com/blog/1035" title="" target="yqual_sub"]   オブジェク...

 

PHPポケモンのプレイはコチラ

 

注目の記事

今からできる!ブログのアクセスを爆UPさせる3大SNS活用法
マーケティング
Facebook,Instagram,Twitter,ブロガー,ブログ
今からできる!ブログのアクセスを爆UPさせる3大SNS活用法

  ブログを収益化させたいけど、なかなかアクセス数が増えない 記事の質は高いのに、その良さをどうやって伝えれば良いかわからない   SEO対策をする上でも、収益化するためにも記事のクオリティは重要です。 しかし、せっかく良い記事を書いていても、そのブログや記事の存在を伝えることができなけれ...

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

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

ブログで生活するための7つの道のり 〜収益化と拡散の方法教えます〜
ライティング
Facebook,Google AdSense,Twitter,ノマドワーク
ブログで生活するための7つの道のり 〜収益化と拡散の方法教えます〜

  ブログで生活したい   毎日数時間、ブログを書くだけで生きていける、そんな夢のような生活を実現させたいと思い描く人は多いですが、簡単なことでは有りません。 ですが、やらなければいけないことがわかっていれば、収益化するのは簡単です。   今回は「ブログで生活するための7つの道のり」をテ...

ビジネス系次世代ブログ!?無料で企画書が読める「机上の空論」とは
ビジネスモデル
ビジネス系次世代ブログ!?無料で企画書が読める「机上の空論」とは

  この記事は、私の考えたビジネスモデルを紹介するコーナーです。考えるだけで辞めたものや、コストやリスクを考えて断念したもの、そこまでニーズがないと判断したものなど様々なので、読んだ方は自分なりの見解や根拠を踏まえて判断したり、各自ビジネスの参考資料としてご活用ください。   このブ...

【無料】早起きをして神戸へ行こう!「為になる雑談朝活」
イベント
三宮,朝活,神戸
【無料】早起きをして神戸へ行こう!「為になる雑談朝活」

  朝活を実施することになりましたので、その目的な概要をまとめました。 神戸三宮での開催を予定しておりますので、もしお近くにお住まいの方で日時が会いましたらご参加ください。 土日祝辺りで週1日程度の不定期開催を予定しています。学びにつながる、けど参加しやすい雑談形式ということを主としています...

HPバーアニメーション 後編 フロント側の対応 PHPポケモン 44
プログラミング
PHP,PHPポケモン,ポケモン
HPバーアニメーション 後編 フロント側の対応 PHPポケモン 44

HPバーアニメーション それでは前回に続き、HPバーのアニメーションづくりをしていきましょう。前回、メッセージに合わせてレスポンスを返却するというサーバー側の仕組みを作成しました。なので、今回はそれをフロント側で受け取り、タイミングよくアニメーションで再現します。   フロント側(js)の処理 前回...

バーアニメーションの不具合対応編 PHPポケモン 54
プログラミング
PHP,PHPポケモン,ポケモン
バーアニメーションの不具合対応編 PHPポケモン 54

最近は細々した対応が多くて「早く次のステップに進めよ!」と思っている方も多いでしょう。 ご意見ごもっともですが、残っている対応が意外にも追加しなければいけない処理が多く苦戦しているのが実情だったりします。そして、そのおかげか試行回数が多くなり見過ごしていた不具合や修正不備がポロポロ出てきていま...

連続攻撃技と一撃必殺技編 PHPポケモン39
プログラミング
PHP,PHPポケモン,ポケモン
連続攻撃技と一撃必殺技編 PHPポケモン39

連続攻撃技とは 追加効果だけでは処理できない技が、初代に限定していても数多くあります。その一つが「連続攻撃技」です。  連続攻撃技 https://wiki.ポケモン.com/wiki/連続攻撃技 連続攻撃技はさらに4パターンに分かれる。 攻撃回数が2回固定であるもの 攻撃回数が3回固定であるもの 攻撃回...

カテゴリ

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