クラスとインスタンス

クラスとインスタンスはプログラミングを学ぶ上で非常に重要な考え方で、次回以降に学習するPDOもクラスの1つです。
少し難しいかもしれませんが、しっかり理解して次に進みましょう。

クラスとは


設計図。またはある実体を生成するために定義された概念のようなもの。
ロボットや車の設計図によく例えられます。

ここではたい焼きの型に例えて考えてみましょう。
たい焼きの型(クラス)を使ってたい焼き(インスタンス)を作ることイメージしてみましょう。

インスタンスとはクラスという設計図を基に作成した実体。
同じたい焼きの型(クラス)からクリーム入りのたい焼き、あんこ入りのたい焼きなど様々なたい焼き(インスタンス)を作ることができます。

 

さっそくたい焼きを作ってみましょう。

<?php
class Taiyaki {
    public $content

    public function __construct($nakami) {
        $this->content = $nakami;
    } 

    public function whatIsContent() {
        echo '中身は'.$this->content.'だよ。';
    }
}
// あんこのたい焼き 
$taiyaki_anko = new Taiyaki("あんこ"); 
$taiyaki_anko->whatIsContent(); 
// クリームのたい焼き
$taiyaki_cream = new Taiyaki("クリーム");
$taiyaki_cream->whatIsContent();
?>

上から順に見ていきましょう。

class Taiyaki {
    public $content

まずクラスプロパティを宣言します。
プロパティはクラスが持つ変数のことです。
今回は「たい焼きの中身」を持って欲しいので、$contentという名前を付けました。
名前は通常の変数と同じように自由に付けることができ、いくつでも持たせることができます。

public function __construct($nakami) {
    $this->content = $nakami
}

ここからクラスが持つメソッドを定義していきます。
メソッドとは処理をまとめた物です。
ただ、__constructは特殊で、インスタンスが生成されるときに呼ばれる関数のことです。
初期化のようなものと覚えましょう。

今回は初期化の際に中身(あんこ、クリーム、etc…)を受け取とって、プロパティ($content)に値をセットしています。

$this->content

クラス内のプロパティメソッドにアクセスするためには上のように記述します。$thisは「このクラスの」という意味です。
メソッドチェーンでプロパティやメソッドにアクセスできます。

public function whatIsContent() {
    echo '中身は'.$this->content.'だよ。';
}

ここからはTaiyakiクラスが持つ通常のメソッドです。
中身が何なのか教えてくれるメソッドを作成します。

// あんこのたい焼き
$taiyaki_anko = new Taiyaki("あんこ");
$taiyaki_anko->whatIsContent();
// クリームのたい焼き
$taiyaki_cream = new Taiyaki("クリーム");
$taiyaki_cream->whatIsContent();

それでは実際に型(クラス)からたい焼き(インスタンス)を作ってメソッドの実行まで試してみましょう。
インスタンスを作成する際には new Taiyaki(初期値) といった具合に宣言します。
今回は初期値(__construct)としてたい焼きの中身が必要なので、あんこ、またはクリームを初期値にしてインスタンスを作成します。

インスタンスを$taiyaki_anko変数として宣言しました。

$taiyaki_anko->whatIsContent(); // 中身はあんこだよ。

とすることで関数を呼び出すことができました。

クラスは非常に便利な仕組みです。
ここからはより深く学んでみましょう!


突然ですが質問です。みなさんRPGは好きでしょうか?
そこに出てくる敵ってたくさんいますよね?これは1つずつ作成していると思いますか?
先ほど学習したクラスを使うと効率よく敵が作れそうだと思いませんか?

先ほどの学習内容と以下の点をふまえて、Enemyクラスをまずは自分で作ってみましょう。
・敵を作るときに元になるクラス
・名前(name)、体力(stamina)、攻撃力(attack)のプロパティを持つ
・初期化の際に、名前を決める必要がある。
・sayMayName()というメソッドを作成し、自分の名前を名乗るようにする。

 

 

 

<?php 
    class Enemy {
        public $name;
        public $stamina;
        public $attack;

        public function __construct($name) {
            $this->name = $name;
        }

        public function sayMyName() {
            echo $this->name.'があらわれた!';
        } 
    }
    // Enemyクラスからスライムを作る
    $slime = new Enemy('スライム');
    $slime->sayMyName();
 ?>

ここからはさらにEnemyクラスを修正していきましょう。
まずは初期化メソッドを修正し、体力と攻撃力を設定できるようにしましょう。

public function __construct($name, $stamina = 100, $attack = 10) {
    $this->name = $name;
    $this->stamina = $stamina;
    $this->attack = $attack;
}

関数の引数はいくつ設定しても大丈夫です。
引数に初期値を設定しておくと、インスタンスを作る際に省略することができます。

$slime = new Enemy('スライム');
echo $slime->stamina;
echo $slime->attack;

echo '</br>';

$kuribo = new Enemy('クリボー', 200, 10);
echo $kuribo->stamina;
echo $kuribo->attack;

以下のように表示されましたか?

次は攻撃力を10上げるメソッドをsayMyName()の下に作って実行してみましょう。

public function powerUp() {
    $this->attack += 10;
    echo '攻撃力が'.$this->attack.'になった。</br>';
}
$slime = new Enemy('スライム');
$slime->powerUp();
$slime->powerUp();
$slime->powerUp();
$slime->powerUp();
$slime->powerUp();
$slime->powerUp();
$slime->powerUp();

 

クラスの継承


次はボスモンスターを作ってみましょう。ボスはEnemyクラスの特徴を持った上で、さらに特別なパラメータを持ちます。
そのとき新しいクラスを0から作るのではなく、クラスの継承をします。

class Enemy {
   // 省略
}

class Boss extends Enemy {
    public function specialAttack() {
        echo 'すごい強い一撃!';
    }
}

$boss = new Boss('竜王');
$boss->sayMyName();
$boss->specialAttack();

Enemyクラスは先ほどと同じです。extendsでBossクラスはEnemyクラスを継承します。
継承するとBossクラスはEnemyクラスのプロパティメソッドを自分のものとして持つことになります。
__constructも同じなので、初期値は与えなければいけませんが、Enemyクラスのメソッドを利用できます。

メソッドのオーバーライド


class Boss extends Enemy {
    public function sayMyName() {
        echo 'ボスの'.$this->name.'があらわれた!';
    }

    public function specialAttack() {
        echo 'すごい強い一撃!';
    }
}

継承したクラス(Boss)は継承元のクラス(Enemy)のメソッドを上書きすることができ、オーバーライドといいます。

$slime = new Enemy('スライム');
$boss = new Boss('竜王');
$slime->sayMyName();
$boss->sayMyName();

EnemyクラスとBossクラスのインスタンスを作成して、試してみましょう。

このようなクラスとインスタンスのことをオブジェクトといい、データをひとかたまりにして管理することをオブジェクト指向と呼びます。

最後にクラスを使用する際によく使うワードを学習します。

アクセス権(public,private,protected)


先ほどから何度か登場しているpublic。これはどこからアクセスできることを表します。

public どこからでもアクセス可能
private そのクラス内からのみアクセス可能。子クラスからのアクセスは不可。
protected そのクラスと親子関係(継承したクラス)ならアクセス可能。

class Enemy { 
    private $name; 
    // 以下略 
} 
$slime = new Enemy('スライム');
echo $slime->name;

アクセス権を変更して、結果の違いを確認してみてください。
privateに変更するとちゃんとエラーになりましたか?

次は$nameのアクセス権がprivateの状態でsayMyName()メソッドを実行してみましょう。
結果はどうなると思いますか?少し考えてみてください。

class Enemy {   
    private $name;
    public function sayMyName() {
        echo $this->name.'があらわれた!'; 
    }
    // 以下略
}
$slime = new Enemy('スライム');
$slime->sayMyName();

 

 

 

結果はスライムがあらわれた!と表示されます。


privateなプロパティ、フィールドにも同じクラス内のpublicなメソッドからはアクセスすることができます。
このように外部からのアクセスを制限することをカプセル化といいます。しばらくはすべてpublicにしておけば問題ないです。
現場に出てからはこのような仕組みが必要とされる場合があるので、各自で調べてみましょう。

static キーワード


staticを付けたプロパティ、メソッドはインスタンスを通さずに参照することができます。
通常のプロパティはインスタンスごとに異なる値を持ちますが、staticなプロパティはクラスで共通の値を参照している点に注意しましょう。

class Enemy {
    public $name;
    public $stamina;
    public $attack;
    public static $count = 0;

    public function __construct($name, $stamina = 100, $attack = 10) {
        $this->name = $name;
        $this->stamina = $stamina;
        $this->attack = $attack;
        Self::$count += 1;
    }

    public static function getEnemyCount() {
        echo Self::$count.'体の敵を作りました!';
    }
}

$countをstaticなプロパティとして宣言します。
コンストラクタ内でインスタンスが生成されると+1されます。
通常にプロパティと違ってクラス名::プロパティでアクセスします。
クラス内の場合は自信を表すselfを使用します。
staticなメソッドを作成しましょう。

Enemy::getEnemyCount();
$slime_A = new Enemy('スライム');
$slime_B = new Enemy('スライム');
$slime_C = new Enemy('スライム');
$slime_D = new Enemy('スライム');
Enemy::getEnemyCount();

 

クラスとインスタンスについては以上です。
1回で理解するのはなかなか難しい章になるので、繰り返し復習しましょう。

カテゴリー

アーカイブ

Close Bitnami banner
Bitnami