プログラミング

ピカチュウから学ぶオブジェクト指向 〜入門編〜 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ポケモンのプレイはコチラ

 

注目の記事

有料ノートが公開停止!?プラットフォーム依存の危険性とは
雑記
note,YouTube,ブログ
有料ノートが公開停止!?プラットフォーム依存の危険性とは

  「いままでのnoteがいきなり公開停止になった」 「YouTubeであげていた人気動画が削除された」   規約変更、違反などを理由にこういった被害は年々増えています。自覚して悪意あるコンテンツを作っているユーザーであれば当然の結果だと言ってしまえば済むことですが、努力して収益化する糸口を見つけ...

戦闘不能による交代編 PHPポケモン84
プログラミング
PHP,PHPポケモン,ポケモン
戦闘不能による交代編 PHPポケモン84

戦闘不能による交代 ポケモンが戦闘不能になった際、もし手持ちに戦える状態のポケモンが残っていれば「交代」か「逃げる」の2択になります。今までは手持ちポケモンが1匹のみで判定を行っていたので、今回は交代の選択肢も含めて勝負の判定の見直しをしていきます。   パーティーを含めた勝負判定 味方または...

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

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

PHPポケモン「バトルシステム実装編〜ダメージ計算〜」20
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「バトルシステム実装編〜ダメージ計算〜」20

バトルシステムの実装  今回はバトルシステムの中でもメインとなるダメージ計算と、命中判定の部分を実装していきます。   ダメージ計算  ポケモンのダメージ計算は初代から現在までそこまで大きな変化はありません。最新世代ではダメージに関係する要素(アイテム等)が多く、それにより補正値の修正はあります...

毎日継続をするためのコツ
雑記
毎日継続をするためのコツ

定期的にコラムを書きたくなるので、今回は「毎日継続をするためのコツ」というテーマで自分が意識していることや、感じたことを書き綴っていきます。 決して開発や業務で追われていたり、PHPポケモンの大幅見直しを迫られているわけではありません。   毎日継続するために  ブログや学習など、毎日継続...

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

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

WordPressをローカルと本番環境で同じ状態にするために理解しておきたい3つのポイントを徹底解説
プログラミング
PHP,phpMyAdmin,WordPress
WordPressをローカルと本番環境で同じ状態にするために理解しておきたい3つのポイントを徹底解説

  WordPressで作ったサイトは通常のサイトと違い、DBが絡んでくるためローカル環境と本番環境を同一の状態で稼働させるには設定や更新されるディレクトリの知識が必要になります。 今回は、WordPressを使ったサイトを作成している人や、開発に挑戦しようとしている人に向けて、ローカルで作ったWordPressのサイ...

あばれる編(あばれる・はなびらのまい)PHPポケモン52
プログラミング
PHP,PHPポケモン,ポケモン
あばれる編(あばれる・はなびらのまい)PHPポケモン52

あばれる状態とは 技を使うと、しばらくの間その技のみしか使用できなくなる技があります。その状態を「あばれる状態」と言います。 あばれる状態(ポケモンwiki) https://wiki.ポケモン.com/wiki/あばれる_(状態変化) あばれるの効果 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 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 独立 神戸 福祉 秘密鍵 翻訳 自己啓発 英語 見積書 計算機 読書 起業 迷惑メール 配列 銀の弾丸 集客 雑学力