Lesson 10

クラス

Lesson 10 Chapter 1
クラスを作成する

Lesson10ではクラスについて学習をします。クラスを使用せずとも開発を行うことは可能ですが、クラスの概念や使用は必須に近い存在となっています。

クラスとは

クラスとはこれまで使用してきた関数や変数のプログラムを一つのまとまりにしたものです。クラスの概念は開発を行う場合、避けては通れない項目となっているので、しっかりと学んでいきましょう。

クラスの作成
class クラス
{
  // プロパティ(値)
  public $変数 = 値;

  // メソッド(関数)
  public function メソッド(){
    // 処理
  }
}

クラスの定義

以下構成でファイルを作成し、クラスの作成を行ってみましょう。 見てみるとわかるようにこれまで使用してきた変数や関数を囲っているものがクラスです。そしてクラスを定義する際は「class クラス名」として定義します。

XAMPP > htdocs > Lesson10 > index.php

index.php
<?php
class TestClass
{

  public $message = "Hello";

  public function TestMessage()
  {
    // 処理
  }

}

プロパティの定義

プロパティとは今まで使用してきた変数のことを指します。役割はこれまでと同様ですが、クラスの中で定義された変数はプロパティと呼ばれている為、変数とプロパティの区別をつけておきましょう。

index.php
<?php
class TestClass
{

  public $message = "Hello";

}

アクセス修飾子

プロパティを定義する際にアクセスできる範囲のようなものを指定することができます。

①public

public
<?php
class TestClass
{

  public $message = "Hello";

}

publicを始めプロパティを定義することによりどこからでもアクセスが可能なプロパティとなります。どこからでもアクセス可能とは、例えばAのファイルで定義したプロパティをBのファイルからでも使用可能といったことです。publicは最も使用頻度の高いアクセス修飾子になります。

②protected

protected
<?php
class TestClass
{

  protected $message = "Hello";

}

protectedを始めプロパティを定義することにより自身のクラスと継承したクラスからのみアクセスが可能なプロパティとなります。継承についてはこの後のchapterで学習しますが、「AクラスはBクラスを継承しますよ」と宣言した場合にAクラスとBクラスでは使用可能なプロパティです。2番目にアクセスできる範囲の広いアクセス修飾子です。

③private

private
<?php
class TestClass
{

  private $message = "Hello";

}

privateを始めプロパティを定義することにより自身のクラスからのみアクセスが可能なプロパティとなります。自身のクラスからのみであるため、例え継承していたとしても定義しているクラスからでしか使用ができません。最も使用できる範囲の狭いアクセス修飾子です。

メソッドの定義

メソッドとはこれまで使用してきた関数のことを指します。クラス内で定義された関数をメソッドと呼びます。役割はこれまでと同様ですが、定義する場所によってこちらも呼び方が変化するので、区別できるように認識しておきましょう。

index.php
<?php
class TestClass
{

  public function TestMessage()
  {
    // 処理
  }

}

アクセス修飾子

メソッドにもプロパティと同様、アクセスできる範囲を指定することができます。

①public

public
<?php
class TestClass
{

  public function TestMessage()
  {
    // 処理
  }

}

publicを始めメソッドを定義することによりどこからでもアクセスが可能なメソッドとなります。どこからでもアクセス可能とは、例えばAのファイルで定義したメソッドをBのファイルからでも使用可能といったことです。publicは最も使用頻度の高いアクセス修飾子になります。

②protected

protected
<?php
class TestClass
{

  protected function TestMessage()
  {
    // 処理
  }

}

protectedを始めメソッドを定義することにより自身のクラスと継承したクラスからのみアクセスが可能なメソッドとなります。継承した場合に自身のクラスと継承先のクラスでは使用可能なメソッドです。2番目にアクセスできる範囲の広いアクセス修飾子です。

③private

private
<?php
class TestClass
{

  private function TestMessage()
  {
    // 処理
  }

}

privateを始めメソッドを定義することにより自身のクラスからのみアクセスが可能なメソッドとなります。自身のクラスからのみであるため、例え継承していたとしても定義しているクラスからでしか使用ができません。最も使用できる範囲の狭いアクセス修飾子です。

まとめ

以上がクラスの基本となる定義です。

クラス作成まとめ

  • クラスは処理や値をまとめたもの。
  • クラス内で定義された関数をメソッドと呼ぶ。
  • クラス内で定義された変数をプロパティと呼ぶ。
  • 3種類のアクセス修飾子(public / protected / private)が存在する。

Lesson 10 Chapter 2
インスタンス作成

インスタンスの作成とは

インスタンスの作成とは一言で、定義したクラスを実際に使用していくために必要な準備になります。

インスタンスの作成
new クラス();

インスタンスを作成する

上記を基に、最初に定義したクラスに記述を追加します。

XAMPP > htdocs > Lesson10 > index.php

index.php
<?php
class TestClass
{

  public $message = "Hello";

  public function TestMessage()
  {
    return "メソッドの呼び出し成功";
  }

}

// インスタンスの作成
$testClass = new TestClass();

このように「new クラス名」とするだけでインスタンスの作成は完了になります。

プロパティの呼び出し

クラス内のプロパティを呼び出す際は作成したインスタンスを使用して呼び出します。

index.php
<?php
class TestClass
{
  public $message = "Hello";

  public function TestMessage()
  {
    return "メソッドの呼び出し成功";
  }
}

$testClass = new TestClass();

echo $testClass->message;

これまでは「echo $変数名」として呼び出す場合が多くありましたが、クラス内のプロパティを呼び出す際は

クラスのインスタンス → プロパティ

とインスタンスからプロパティへアクセスして呼び出すルールがあります。又、この場合$は不要なので注意しましょう。

出力結果
Hello

メソッドの呼び出し

クラス内のメソッドを呼び出す際も作成したインスタンスを使用して呼び出します。

index.php
<?php
class TestClass
{
  public $message = "Hello";

  public function TestMessage()
  {
    return "メソッドの呼び出し成功";
  }
}

$testClass = new TestClass();

echo $testClass->TestMessage();

クラス内のメソッドを呼び出す際も同様です。

クラスのインスタンス → メソッド

とインスタンスからメソッドへアクセスして呼び出すルールがあります。

出力結果
メソッドの呼び出し成功

擬似変数

擬似変数で$thisというものが存在します。クラスを扱う上で$thisを使用する機会が多くあるので、こちらも覚えておきましょう。

間違ったプロパティの参照

index.php
<?php
class TestClass
{
  public $message = "Hello";

  public function TestMessage()
  {
    return $message;
  }
}

$testClass = new TestClass();

echo $testClass->TestMessage();

例えば上記のようにクラス内で定義した$messageプロパティをTestMessageメソッドで扱いたい場合があるとします。まずはTestMessageメソッド内で$messageプロパティを使用して見ましょう。

出力結果
Warning: Undefined variable $message in ...

$messageプロパティを参照できずエラーが発生してしまいました。

正しいプロパティの参照

index.php
<?php
class TestClass
{
  public $message = "Hello";

  public function TestMessage()
  {
    return $this->message;
  }
}

$testClass = new TestClass();

echo $testClass->TestMessage();

ここで擬似変数$thisを使用してあげます。$thisは「このクラス内の〜」というイメージで参照することができます。今回は「このクラス内のmessageプロパティ」としたいので、TestMessageメソッド内の追記を変更しましょう。この時$messageの$は不要なので使わないように注意してください。

出力結果
Hello

このように擬似変数$thisを使用することで、メソッドからプロパティを参照することができました。

まとめ

インスタンス作成のまとめ

  • クラスを使用するためにはインスタンスの作成を行う必要がある。
  • 作成したインスタンスからプロパティやメソッドへアクセスすることで処理や値を呼び出すことができる。
  • クラス内でプロパティを呼び出す際は擬似変数$thisを使用する。

Lesson 10 Chapter 3
コンストラクタ

コンストラクタとは

コンストラクタとは、インスタンスの作成時に自動的に実行されるメソッドのことを指します。つまり「new クラス名()」が実行されたタイミングで実行されるメソッドがコンストラクタです。インスタンスの作成時に必ず実行したい処理やプロパティの初期化を主に行います。

コンストラクタ
<?php
class クラス
{
  function __construct(){
    // インスタンス作成時に実行する処理
  }
}

コンストラクタの定義

早速例文を使って確認してみましょう。コンストラクタの定義に関しては名前が決まっています。他のメソッドのように任意ではなく「__construct」でなくてはいけないルールがあるので注意しましょう。

XAMPP > htdocs > Lesson10 > index.php

index.php
<?php
class TestClass
{
  public $message = null;

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

  public function TestMessage()
  {
    return $this->message;
  }
}

// インスタンスの作成
$testClass = new TestClass("こんにちは");
echo $testClass->TestMessage();

コンストラクタの動作確認

それではブラウザを確認して見ましょう。

出力結果
こんにちは

処理は問題なく動いていることが確認できました。

処理の初期化とは

コンストラクタが使用される場面で最も多いのはプロパティの初期化になります。以下のコードを確認してください。

index.php
<?php
class TestClass
{
  public $message = "こんにちは";

  function __construct()
  {

  }

  public function TestMessage()
  {
    return $this->message;
  }
}

// インスタンスの作成
$testClass = new TestClass();
echo $testClass->TestMessage();

例えばこのように$messageのプロパティを固定にした場合、必ず「こんにちは」と出力されます。これ以外、返さない処理であればむしろ好都合ですが、作成したインスタンス毎にプロパティを変えたい場合は不向きです。下記のように記述に変更を加えます。

index.php
<?php
class TestClass
{
  public $message = null;

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

  public function TestMessage()
  {
    return $this->message;
  }
}

// インスタンスの作成
$testClass = new TestClass("こんばんは");
echo $testClass->TestMessage();

このようにnullとして$messageを定義し初期化を行います。TestClassもAファイルだけでなくB,Cファイルから参照されインスタンスが作成される度に値を柔軟に変更し、受け取った値をreturnすることができるように準備のようなものを行っています。それではブラウザの結果を確認して見ましょう。

出力結果
こんばんは

まとめ

コンストラクタ

  • コンストラクタは「__construct」と決まっていおり命名することはできない。
  • コンストラクタは1つのクラスに1つのみ定義可能。
  • コンストラクタに設定した処理はインスタンスの作成時に自動的に実行される。

Lesson 10 Chapter 4
クラスの継承

クラスの継承とは

クラスの継承はextendsと定義することによって、クラスで定義しているメソッドやプロパティを別のクラスで使用することが可能となります。継承を行うメリットとしては似たような処理をそれぞれのクラスに記述せずとも継承することで使用できる為、コード量が最低限に抑えられ保守性に優れている点です。又、以前学習したアクセス修飾子のprivateは継承しても使用できないので注意しておきましょう。

クラスの継承
<?php
class 親クラス
{
  // 処理
}

class 子クラス extends 親クラス
{
  // 処理
  // 親クラスのプロパティやメソッドを使用できる
}

継承の仕方

それでは実際にクラスを定義し、クラスを継承して見ましょう。以下構成で2つのファイルを準備してください。

親クラスの定義

XAMPP > htdocs > Lesson10 > weather.php

weather.php
<?php
class Weather
{
  public $weather = "";

  public function getWeather()
  {
    return $this->weather;
  }

  // ④
  public function setWeather($weather)
  {
    $this->weather = $weather;
  }
}

子クラスの定義

「extends Weather」の部分で親クラスを継承しています。継承したことにより親クラス内のメソッドやプロパティを子クラスでも使用が可能になります。

XAMPP > htdocs > Lesson10 > today.php

today.php
<?php
require_once("weather.php")

// ①
class Today extends Weather
{
  public function Temperature()
  {
    return "30";
  }
}

// ②
$today = new Today();

// ③
$today->setWeather("晴れ");

// ⑤
echo "天気は" . $today->getWeather() . "。最高気温は" . $today->Temperature() . "度です";

これでクラスの継承は完了です。

処理の流れを確認

動作確認の前に処理の流れを確認していきます。

①継承する

 「extends Weather」の部分でWeatherクラスの継承。Weatherクラス内のメソッドやプロパティが使用可能となる。

②Todayクラスのインスタンス作成

 子から親のメソッドやプロパティを使用していくのでインスタンスを作成。

③親クラスのメソッドへアクセス

 作成したインスタンス$todayから親クラスのsetWeatherメソッドで値を代入。

④親クラス内の動き

 setWeatherメソッドの処理「$this->weather = $weather」により$weatherに「晴れ」が代入。

⑤出力する

 親クラスの「$today->getWeather()」と子クラスの「$today->Temperature()」と文字列を結合し文章が出力される。

継承の動作確認

出力結果
天気は晴れ。最高気温は30度です

getWeatherメソッドは親のクラスで定義されているメソッドですが、継承したことで子クラスからでもアクセスが可能となりました。少し記述量は増えましたが、このようにWeatherクラスを継承(extends)することでTodayクラスのインスタンスを作成すれば$todayからWeatherクラスのメソッドやプロパティのアクセスが可能です。

オーバーライド

続いてはオーバーライドについて学習していきます。オーバーライドとは子クラスから親クラスのプロパティやメソッドの内容を上書きすることを言います。

オーバーライドをしない場合の動作

weather.php
<?php
class Weather
{
  public function todayWeather()
  {
    return "晴れです";
  }
}
today.php
<?php
require_once("test.php");

// 子クラス
class Today extends Weather
{

}

$today = new Today();
echo $today->todayWeather();
出力結果
晴れです

継承した親クラスのメソッドを呼び出せていることが確認できます。

オーバーライドをした場合の動作

オーバーライドするときは親クラスとメソッドやプロパティと同じ命名で子クラスに定義します。

weather.php
<?php
class Weather
{
  public function todayWeather()
  {
    return "晴れです";
  }
}
today.php
<?php
require_once("test.php");

// 子クラス
class Today extends Weather
{
  public function todayWeather()
  {
    return "雨です";
  }
}

$today = new Today();
echo $today->todayWeather();
出力結果
雨です

このように親のクラスと同じ命名のメソッドやプロパティを子クラスで定義することにより、親クラスのメソッドやプロパティの内容を上書きすることができます。継承は一つのファイルだけでなく、複数のファイルから行なわれることがほとんどの為、親クラスの記述を直接変更するよりも子クラスからオーバーライドすることでリスクを抑えることができます。

まとめ

継承のまとめ

  • クラスを継承することで継承先のクラスに定義されているプロパティやメソッドを使用することができる。
  • クラスの継承は「class 親クラス extends 子クラス」とextendsを用いて継承する。

Lesson 10 Chapter 5
クラスの抽象化

クラスの抽象化とは

クラスの抽象化を行うことで、処理の流れや名称を統一化させ、利便性が増すと同時にまとまりのあるコードを記述することができます。又、抽象化されたクラスは継承される前提のクラスとなり、抽象化されたクラス内で定義された抽象メソッドは必ず使用しなければならないルールも存在します。クラスの抽象化は「abstract」と定義します。

抽象化
<?php
abstract 抽象クラス名{
    abstract アクセス修飾子 function 抽象メソッド名();
}

抽象化の仕方

抽象クラスの作成

XAMPP > htdocs > Lesson10 > translation.php

translation.php
<?php
abstract class Translation
{
  public $message = "";
  abstract public function Message();
}

抽象クラスの定義は「abstruct」から始まります。又、抽象クラス内で定義しているメソッドに処理は記述しません。注意点として、抽象クラスを継承したクラスでは抽象クラスで定義されているプロパティとメソッドを使用する必要があります。

子クラスの作成

XAMPP > htdocs > Lesson10 > language.php

language.php
<?php
require_once("translation.php");

// 日本語で挨拶するクラス
class Japanese extends Translation
{
  function Message()
  {
    return "日本語で挨拶は" . $this->message;
  }
}

// 英語で挨拶するクラス
class English extends Translation
{
  function Message()
  {
    return "英語で挨拶は" . $this->message;
  }
}

$japanese = new Japanese();
$japanese->message = "こんにちは";
echo $japanese->Message();

echo "<br>";

$english = new English();
$english->message = "Hello";
echo $english->Message();

JapaneseクラスとEnglishクラスを用意しました。メソッド処理内容は日本語と英語の挨拶を返すほぼ同じような処理です。それぞれの抽象化クラスを継承しているので、extends Translationの記述をしています。

処理内容

①JapanクラスとEnglishクラスのインスタンスを作成。

②クラス内のプロパティ$messageへ「こんにちは」と「Hello」を代入。

③メソッドを呼び出し処理を実行する。

抽象クラスの動作を確認

出力結果
日本語で挨拶はこんにちは
英語で挨拶はHello

問題なく処理が実行されていることが確認できます。

抽象化を行わない場合

抽象化と継承を行わない場合は以下のような記述になる可能性があります。

language.php
<?php
class Japanese
{
  function JapaneseMessage($japaneseMessage)
  {
    return "日本語で挨拶は". $japaneseMessage;
  }
}

class Eng
{
  function EnglishGreeting($greeting)
  {
    return "英語で挨拶は" . $greeting;
  }
}

$japanese = new Japanese();
echo $japanese->JapaneseMessage("こんにちは");

echo "<br>";

$english = new Eng();
echo $english->EnglishGreeting("Hello");

一概に上記とは言えませんが、チームでの開発を行なった場合、人それぞれメソッド名やプロパティ名など自由に命名することができます。このような統一性のないクラスを見ていかがでしょうか。似たような、又は同じ処理なのに命名が違うと見づらく混乱を招く可能性も高くあります。

抽象化を行っている場合

ここでもう一度抽象化したクラスを見て見ましょう。

language.php
<?php
require_once("translation.php");

// 日本語で挨拶するクラス
class Japanese extends Translation
{
  function Message()
  {
    return "日本語で挨拶は" . $this->message;
  }
}

// 英語で挨拶するクラス
class English extends Translation
{
  function Message()
  {
    return "英語で挨拶は" . $this->message;
  }
}

$japanese = new Japanese();
$japanese->message = "こんにちは";
echo $japanese->Message();

echo "<br>";

$english = new English();
$english->message = "Hello";
echo $english->Message();

抽象化を行っている分、若干記述が増えてる部分もありますが、先ほどに比べて見やすさはいかがでしょうか。例えばJapaneseクラスの処理が理解できてしまえば、統一感があることから「Englishクラスもこのような処理だろう」とある程度想定しながら作業を進められることでしょう。

抽象化のメリット

抽象化を行うことでこのようなルールを設けることができます。ルールが存在することで統一感のあるコードを実現することが可能なため、個人だけに限らずチームでの作業効率が大幅に向上させることが可能です。

抽象化の注意事項

注意

  • 抽象クラスでは抽象メソッドを必ず定義する必要がある。
  • 抽象クラスで定義したメソッドやプロパティは必ず使用しなければならない。
  • 抽象化したクラスのインスタンスは作成できない。

まとめ

抽象化のまとめ

  • 抽象化するクラスは継承されることを前提に作成する。
  • クラスを抽象化することによって利便性やまとまりのあるプログラムを記述することが可能。
  • 抽象化したクラス内で定義したメソッドは処理の記述が不要。又、これを抽象メソッドと呼ぶ。