PHPのアクセス修飾子には次の3種類があります。
- public
- protected
- private
よくわからないからとりあえずpublicを付けとく、という経験はないでしょうか?アクセス修飾子の必要性を理解していない時、実は僕はそんなふうにしていました。
その考えが変わったのは、アクセス修飾子の必要性を理解した時です。そこで、以前の僕のようにアクセス修飾子について困っている方に向けて、今回はアクセス修飾子の必要性を説明してみようと思います。
「アクセス修飾子がないとこんなことに困るかもしれないんだー」程度に思っていただけたら嬉しいです。
PHPにおけるアクセス修飾子の必要性
「アクセス修飾子を使い分ける目的って何?」という問いには、次のように答えることができます。
- メンバ変数に変な値が代入されるのを防ぐため
- メンバ変数の変数名を変更する際、広い範囲に変更を加える必要が出るのを防ぐため
※メンバ変数 – クラスの中にある変数
アクセス修飾子がないとこのようなことをするのが難しいからアクセス修飾子が必要であると言えるでしょう。
実際にアクセスを無条件にとりあえずpublicにした時、どんな悪い影響が出るのかをこれから見てみましょう。
アクセス修飾子の必要性①「変な値を代入させない」
アクセス修飾子をとりあえずpublicにした場合、こういう値は代入させないという制限をつけることができなくなってしまいます。
例えば、次のような制限をしたい時を考えてください。
- 生徒の身長を入れるheightという変数を作る。
- このheightにはマイナスの値を入れられないようにする。
ではやってみます。まず、Studentという名前のクラスを作ります。このクラスの中に生徒の身長を入れるheghtという変数をpublicを付けて作ります。
<?php
class Student {
public $height;
}
?>
身長は-160cmというようなマイナスの値になることはありません。そのため、0より小さかったら代入しないという制限のある代入を行うメソッドを使って値をheightに代入させるようにします。
<?php
class Student {
public $height;
function set_height($height) {
if($height>0) {
$this->height = $height;
} else {
echo "身長が不正です。";
}
}
}
?>
これで、もうheightにはマイナスの値が入らないようになったと思う方がいるかもしれません。
確かに、set_heightメソッドを使ってheightに値を代入すれば、マイナスの値の代入を防ぐことができます。しかし、「$student1.height=160;」のようにして直接代入すると、マイナスの値を代入できてしまうんです。
<?php
class Student {
public $height;
function set_height($height) {
if($height>0) {
$this->height = $height;
} else {
echo "身長が不正です。";
}
}
}
$student1 = new Student();
$student1->set_height(-160); //代入されない
$student1->height=-160; //代入される
?>
このようなことから、変数に代入するを制限したい場合には、変数にprivateというアクセス修飾子をつけることでクラス定義の外から直接代入することを防ぐ必要が出てきます。
アクセス修飾子の必要性②「変更箇所を少なくする」
アクセス修飾子にpublicをつけると、クラスの定義の外側にも変数名を書く可能性が出てきます。例えば次のような感じです。
<?php
class Student {
public $height;
}
$student1 = new Student();
$student->height=160; //クラスの外にheightという変数名を書いてしまっている
echo $student->height; //クラスの外にheightという変数名を書いてしまっている
?>
すると、クラス定義の中にある変数名を変更しようとするときに変数名を書いた分だけ変更を加えなければいけなくなります。
実際に変数heightをprevious_heightに変えると、
<?php
class Student {
public $previous_height; //変数heightをprevious_heightに変更
}
$student1 = new Student();
$student->previouse_height=160; //変数heightをprevious_heightに変更
echo $student->previouse_height; //変数heightをprevious_heightに変更
?>
Studentクラスの中にある変数を変えたいだけなのに、クラス定義の外で直接変数に値を代入したり、参照したりしたことにより、クラス定義の外側にも変更する箇所ができてしまっています。
一方で、height変数を作るときにpublicではなくprivateにしておくとどうなるでしょうか?
<?php
class Student {
private $height;
function set_height($height) {
$this->height = $height;
}
function get_height() {
return $this->height;
}
}
$student1 = new Student();
$student1->set_height(160);
echo $student1->get_height();
?>
class定義の外では、「$student->height=160;」のようにして直接値を代入したり、参照したりすることはできなくなります。
言い方を変えると、必然的にsetterやgetterを使って間接的に値を代入したり参照したりする必要が出てきます。すると、クラス定義の外側には、メンバ変数の変数が書かれなくなります。
これにより、変数名をheightからprevious_heightにしたとしても、変更するのはクラス定義の中だけで済みます。
<?php
class Student {
private $height;
function set_height($height) {
$this->height = $height;
}
function get_height() {
return $this->height;
}
}
$student1 = new Student();
$student1->set_height(160); //クラス定義の外には変更が必要ない
echo $student1->get_height(); //クラス定義の外には変更が必要ない
?>
一見、「それだけのことか」と思ってしまうかもしれません。僕も初めはそう思いました。しかし、大人数での開発では複数のphpファイルを作る可能性もあるということを考えてみましょう。
もしも、1つのファイルAにクラス定義が書かれていて、他の複数のファイルでファイルAに定義したクラスの中の変数を直接参照していたとするとどうでしょうか?
たった1つファイルに含まれる変数を変えるために、その変数が参照されているファイル全てのファイルを変更しなければなりません。
このようなことから、アクセス修飾子をprivateにしてクラスの外からは直接クラスの中の変数を参照できないようにする必要があるんです。
必要性を知っていると、躊躇なく書ける
アクセス修飾子の存在を知って、第一に思うのは次のようなことではないでしょうか?
アクセス修飾子の必要性って何?
もちろんアクセス修飾子について調べると、次のようなことを「メンバ変数には直接触っちゃいけない。隠すべき」的なことを目にすると思います。
ただ、「じゃあなんで触っちゃダメなの?なんで隠すべきなの?」という疑問が出てくることでしょう。
このような疑問を持ち続けている間って確信を持てなくて、アクセス修飾子を書くことを躊躇しちゃいますよね。
アクセス修飾子に限らず、なんとなく書かなくちゃいけない雰囲気のやつってたくさんあります。必要性を知っておけばプログラムの内容を考えることに集中できます。
コメント