クラスというのはあくまで設計図であり、インスタンス化することによって初めて実体化します。
一旦実体化されたクラスのインスタンスは、当然元のクラスとは別のものです。
一つのクラスから複数のインスタンスを作成しても、それぞれお互いには無関係になります。
一枚の設計図から複数の家を建てても、それぞれの家が無関係なのと同じことです。
例によって例外があります。
今回は例外のひとつ、スタティック変数について扱ってみます。
通常のインスタンス変数がインスタンスに属するのに対し、スタティック変数はクラスに属しています。
設計図の例でいうならば、インスタンス変数は実際に建てられた各家の間取りや床面積等に値します。
ひとつの家の間取りを変更しても、他の家の間取りにはまったく影響しません。
それに対し、スタティック変数は家の設計図そのものをいじくることに値します。
普通の設計図と違うのは、家を建てた後に設計図を変更してもその後に建てる家しか変更されませんが、スタティック変数の変更は全ての家に及ぶことです。
まあ例で説明したところでわかりづらいだけなので、実際に使ってみましょう。
index.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
class test{
//static変数
static $point=0;
function getPoint(){
return self::$point;
}
#↓クラスのおわり
}
$class1=new test();
$val[]=$class1->getPoint();
test::$point=10;
$class2=new test();
$val[]=$class2->getPoint();
$val[]=$class1->getPoint();
print("<pre>");var_dump($val);die();
|
変数宣言の時にstaticを付けることで、その変数はインスタンス変数ではなくスタティック変数になります。
スタティック変数はクラスに属しているため、自分自身のインスタンスを示す$thisではアクセスすることができません。
クラス名::$スタティック変数名という形で直接アクセスします。
最初に$class1->getPointした時点では、$pointは最初のままの0です。
その後self::$point=10と直接スタティック変数$pointを書き換えると、全てのクラスにこの変更が適用されます。
その後newした$class2はもちろん、$class1の$pointも10に変更されてしまいます。
まあ簡単に言うと、クラス内のグローバル変数です。
スタティック変数を使うと何が便利かってSingletonパターンが簡単に作成できます。
singleton.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
//Singletonクラス
class Singleton{
static $single=0;
private function __construct(){}
function getInstance(){
if(!self::$single){
self::$single=new Singleton();
}
return self::$single;
}
#↓クラスのおわり
}
//作成
$a=Singleton::getInstance();
$b=Singleton::getInstance();
//比較
if($a===$b){
print('true');
}else{
print('false');
}
|
普通にnewするとコンストラクタで必ず新しいインスタンスが作成されてしまうので、コンストラクタをprivateにしてnewできないようにしてしまいます。
getInstanceメソッドは、もし既に自分自身が存在していれば自分自身を返します。
その結果何度getInstanceを参照しても、その中身は同じものとなります。
$aと$bという二軒の家を建てたつもりが、実は名前が違うだけで同じ家だったようなものです。
同じ家なので、$a->var=10;したあとに$b->varを参照すると10になっていたりします。
プログラム全体でインスタンスを一つしか作らせたくないようなクラスは、これをextendsして作りましょう。
まあリクエスト一回で終了するPHPにSingletonとかあんまり意味無いような気もしますが。
ログを読み返したら今までずっとインスタンス変数をクラス変数と呼んでいました。
過去のクラス変数はインスタンス変数に脳内変換してください。