プログラミング

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

 

注目の記事

「諦めが上手い人」ほど成功する!正しい目標の立て方とは
雑記
PHP
「諦めが上手い人」ほど成功する!正しい目標の立て方とは

  「諦めたらそこで試合終了ですよ」   漫画の中でも有名なセリフですが、これからあなたは何を読み取りますか? 何か目標を達成するために努力が必要とされますが、その方法がわからずに試行錯誤したり、そもそも挑戦すらできずに終えてしまう人は多いのです。 努力をした人は、ほとんどがそれは結果的...

挫折してしまう人に共通する3つの要因〜解決方法を紹介します〜
雑記
挫折してしまう人に共通する3つの要因〜解決方法を紹介します〜

  仕事が上手くいかない 思ったように学習成果がでない   こういった理由で挫折してしまう人は、意外にも考え方や行動が共通しています。 それが何かを知り、考え方や環境、対応方法を少し変えるだけで、劇的に余裕が生まれて自己肯定ができるようになります。その結果、強い人になれるのです。   今...

甘い誘惑に気をつけよう「わからないことへの対処法」
雑記
甘い誘惑に気をつけよう「わからないことへの対処法」

  最近は開発記事が多めだったので、今回は気分転換も込めてみんな大好きコラムのコーナーです。開発疲れという理由ももちろんありますが、久々に考えを書き綴りたくなったというのが本音です。   今回のテーマは「甘い誘惑に気をつけよう」です。高校生ぐらいまではあまり縁がなかったことでも、大学生・社会...

これをしてはいけません!「よくわかるSEO対策」エンジニアのための基礎知識編
SEO対策
htaccess,HTML,JavaScript,SEO,エンジニア,プログラミング
これをしてはいけません!「よくわかるSEO対策」エンジニアのための基礎知識編

  近年ではWebサイト制作会社や個人事業主はかなり増えてきました。 会社によっては力を入れている部分は異なり、主に「デザイン」「機能(システム)」「SEO」という3つに分けられます。 飽和しているのでは無いかと囁かれている中、この3つすべてを揃えた事業者は意外と少なく、個人となれば更に少なくなります。...

ブログ収益化の道!挫折ポイントの回避方法を徹底解説【アドセンス合格は通過点、意外な収益ポイントとは】
ライティング
Google AdSense,ブログ
ブログ収益化の道!挫折ポイントの回避方法を徹底解説【アドセンス合格は通過点、意外な収益ポイントとは】

  ノマドワークや副業としてブログ単体で稼げるようになりたいと考えている人は多いですが、その大半は挫折してしまいます。 アドセンスの合格までに辿りつけなかったり、合格したは良いものの思うように伸びずに諦めてしまうというのがほとんどです。 実は、そのアドセンスに対する考え方自体が間違いであり...

PHPポケモン「技クラス実装編」14
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「技クラス実装編」14

  前回せっかくBootstrapを使って見た目を整えたにも関わらず、ビューポートの記述が抜けているという凡ミスが発覚したので修正しています。 サーセン。   今回のPHPポケモンでは本格的な技システムを実装していきます。技システムが整えば、皆さん期待のバトルシステムも間近です。セキュリティ面やファイル構成...

動画にカラオケテロップを入れる編集方法【AfterEffectsで色変わりの文字】
動画編集
Adobe,AfterEffects
動画にカラオケテロップを入れる編集方法【AfterEffectsで色変わりの文字】

  動画に声と同じタイミングでテロップを入れたい カラオケのような文字はどうやっていれればいいの?   一見簡単に見えるものも、いざ導入しようとすればどうやればいいかわからない、そんなこと多いのではないでしょうか? 今回はAdobe AfterEffectsを使った方法をご紹介します。些細な編集が動画のク...

PHPポケモン「バトルシステム編〜状態異常1〜」30
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「バトルシステム編〜状態異常1〜」30

状態異常チェック 今回は少し先延ばししていた状態異常判定を一部作成していきましょう。 状態異常では「行動前」と「行動後」に判定するものに分けることができます。 行動前 まひ、ねむり、こおり  行動後 どく、もうどく、やけど   まずは簡単な行動前から実装していきます。行動前に判...

カテゴリ

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