PHP - OOP - 4. アクセス権
続いてプロパティやメソッドを修飾するアクセス権について取り上げます。
アクセス権の記述
アクセス権とはプロパティやメソッドを修飾するキーワードで、外部のPHPプログラムからアクセス可能かどうかを決定するものです。
class MyClass
{
public $myProperty;
public function myMethod($x)
{
echo $this->myProperty . " " . $x;
};
}
たとえば上記の MyClass
クラスであれば $myProperty
プロパティと myMethod
メソッドには public
というアクセス権を指定してます。この public
というアクセス権は外部のPHPプログラムからアクセス可能であることを意味します。
PHPで利用可能なアクセス権には以下の3種類があります。
アクセス権 | 意味 |
---|---|
public | どこからでもアクセス可能 |
protected | そのクラス自身、そのクラスを継承したクラス (および親クラス)からのみアクセス可能 |
private | そのクラス自身からのみアクセス可能 |
もし先ほどのプログラムの $myProperty
プロパティのアクセス権に private
を指定すると以下のようなプログラムを実行できなくなります。
require_once("MyClass.php");
$myClass = new MyClass();
$myClass->myProperty = "Hello"; #=> Fatal error
このように private
や protected
といったキーワードを指定することで外部のPHPプログラムからのアクセスを禁止できます。
どのアクセス権を選ぶかは開発するプログラムの要件によって決まります。一般的には、プログラムの保守性を高めるためにアクセス権はなるべく狭くしておきます。
public
キーワードの利用は必要最低限にとどめておくと良いでしょう。
PHPプログラムの開発(アクセス権の変更)
ここでは簡単な計算機クラス( SimpleCalc
クラス)に定義済みの $number
プロパティについて、アクセス権を public
から private
に変更してみましょう。
<?php
class SimpleCalc
{
private $number;
public function add($x)
{
$this->number = $this->number + $x;
}
public function show()
{
echo $this->number . PHP_EOL;
}
}
また実行プログラム( calc_runner.php
)は前回と同じものを利用しましょう。
<?php
require_once("SimpleCalc.php");
$calc = new SimpleCalc();
$calc->number = 10;
$calc->add(20);
$calc->add(30);
$calc->show();
プログラムを実行すると次のようなエラー( Fatal error
)が出力されます。
$ php calc_runner.php
Fatal error: Uncaught Error: Cannot access private property SimpleCalc::$number in /Users/your_name/Desktop/code-php-db/calc_runner.php:6
Stack trace:
#0 {main}
thrown in /Users/your_name/Desktop/code-php-db/calc_runner.php on line 6
このように SimpleCalc
クラスの $number
プロパティのアクセス権を private
に変更したことで、外部のPHPプログラムから $calc->number = 10;
を実行するとエラーになります。
PHPプログラムの開発(アクセサメソッド)
ここまでのプログラムで $number
プロパティへの直接的な値の代入を禁止することができました。次に、開発の現場でよく使うアプローチとしてアクセサメソッドという手法を紹介します。計算機クラス( SimpleCalc
クラス)に以下のようにメソッドを追加します。
<?php
class SimpleCalc
{
private $number;
public function setNumber($number)
{
$this->number = $number;
}
public function getNumber()
{
return $this->number;
}
public function add($x)
{
$this->number = $this->number + $x;
}
public function show()
{
echo $this->number . PHP_EOL;
}
}
ここでは private
な $number
プロパティにアクセスするための getNumber
、 setNumber
と2つのメソッドを定義しています。 getNumber
メソッドは $number
プロパティの値を戻り値で返し、 setNumber
メソッドは $number
プロパティに引数で受け取った値を保存します。このようなプロパティにアクセスするためのメソッドをアクセサメソッドやGetter/Setterメソッドなどと呼びます。
続いて実行プログラム( calc_runner.php
)の中から実際にアクセサメソッドを呼び出してみましょう。
<?php
require_once("SimpleCalc.php");
$calc = new SimpleCalc();
// $calc->number = 10;
$calc->setNumber(10);
$calc->add(20);
$calc->add(30);
$calc->show();
echo $calc->getNumber() . PHP_EOL;
これまでは $calc->number = 10
のようにプロパティに直接値を代入していましたが、ここでは $calc->setNumber(10)
メソッドを呼び出すことで $number
プロパティに値を代入するようにしています。同様に $number
プロパティの値を取得したい場合も $calc->getNumber()
のようにアクセサメソッドを呼び出すようにします。
それではコマンドラインからプログラムを実行してみましょう。
$ php calc_runner.php
60
60
実行結果から $calc->show()
メソッドによる出力と $calc->getNumber()
メソッドの戻り値の出力を確認できます。
参考:カプセル化
このようにプロパティのアクセス権を private
として外部からの直接的なアクセスを禁止し、メソッド呼び出しを通じて間接的にプロパティを制御することをカプセル化と呼びます。
今回の計算機プログラムにおいては、アクセサメソッドを提供することにあまりメリットが感じられなかったかもしれません。しかしアクセサメソッドを経由してプロパティにアクセスすることで、次のようなプログラミングも可能となります。
public function setNumber($number)
{
if (is_numeric($number)) {
$this->number = $number;
}
}
ここでは setNumber
メソッドに if
文による引数のチェックを追加しています。 is_numeric
関数は引数の値が、数字または数値形式の文字列であるかを調べて論理値を返却します。このように実装することで、外部のプログラムから $number
プロパティに代入する値を数字(あるいは数値形式の文字列)に限定できます。このようなアクセサメソッドを提供することでプロパティへの不正な値の代入を禁止できます。
まとめ
- アクセス権には
public
、protected
、privage
の3つがある - アクセス権によって外部のプログラムからプロパティやメソッドへのアクセスを制限できる
- プロパティやメソッドにアクセス権を定義できる