PHP - OOP - 5. アクセサメソッド
ここまでのプログラムで $number
プロパティに private
キーワードを付与することで、プロパティへの直接的な値の代入を禁止することができました。次に、開発の現場でよく使うアプローチとしてアクセサメソッドという手法を紹介します。
アクセサメソッドの定義
図の矢印の方向に注目してください。private
な $myProperty
プロパティにアクセスするために2つのメソッドを追加しています。
setMyProperty
メソッド$myProperty
プロパティに値を代入する
getMyProperty
メソッド$myProperty
プロパティの値を取得する
外部からアクセスできないプロパティに対して、プロパティに対して値を代入するメソッドと値を取得する2つのメソッドを定義しています。これら2つのメソッドのことをアクセサメソッド(Getter/Setterメソッド)などと呼びます。
以前に作成している MyClass.php
ファイルにアクセサメソッドを定義してみましょう。
<?php
class MyClass
{
private $myProperty;
public function myMethod($x)
{
echo $this->myProperty . " " . $x . PHP_EOL;
}
public function setMyProperty($myProperty)
{
$this->myProperty = $myProperty;
}
public function getMyProperty()
{
return $this->myProperty;
}
}
ここでは $myProperty
プロパティに対して setMyProperty
メソッドと getMyProperty
メソッドの2つをアクセサメソッドとして定義しています。
アクセサメソッドは名前の付け方を工夫します。2つのメソッドが
setプロパティ名
、getプロパティ名
となっている点に注目してください。アクセサメソッドはこのようにアクセス対象となるプロパティに対して値を設定する(setする)メソッドと値を取得する(getする)メソッドとして定義します。
次に呼び出し元のプログラム( my_class_runner.php
)からアクセサメソッドを利用する様子を確認してみましょう。
<?php
require_once("MyClass.php");
$myClass = new MyClass();
# $myClass->myProperty = "Hello"; #=> Fatal error
$myClass->setMyProperty("Hello");
echo $myClass->getMyProperty(); # => Hello
以前のようにプロパティへの直接的なアクセスは禁止されていますが、アクセサメソッドを経由して、インスタンスの持つプロパティにアクセスできているのがわかります。
PHPプログラムの開発(アクセサメソッド)
計算機プログラムの例題に戻りましょう。ここでは簡単な計算機クラス( SimpleCalc
クラス)に定義済みの $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
プロパティに代入する値を数字(あるいは数値形式の文字列)に限定できます。このようなアクセサメソッドを提供することでプロパティへの不正な値の代入を禁止できます。
またアクセサメソッドは必ずしもGetter、Setterの2つを一緒に定義する必要はありません。プロパティへの値を代入するSetterメソッドだけを定義する場合や、値を取得するGetterメソッドだけを定義する場合もあります。
まとめ
- アクセサメソッドとは
private
なプロパティなど外部からアクセスできないプロパティを操作するメソッド - プロパティの値を取得するGetterメソッドとプロパティに値を代入するSetterメソッドの2つで構成される
- Getter/Setterメソッドと呼ぶこともある