前回のintArray.phpをちょっとだけ改造。
intArrayの各要素には$int['a']といった形でアクセスできますが、$int->aとしようとすると、勝手にintArray::aというメンバが作成されてしまいます。
では$int->aの挙動の変更は出来ないのか。できます。
intArray.class.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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
class intArray implements ArrayAccess,IteratorAggregate,Countable{
//配列
private $arr=array();
//コンストラクタ
function __Construct(){}
//__set
public function __set($a,$b){
return $this->offsetSet($a,$b);
}
//__get
public function __get($a){
return $this->offsetGet($a);
}
//値セット ArrayAccess::offsetSet
public function offsetSet($a,$b){
//引数が数値かチェック
if(!is_int($b)){
//数値でなければエラー
$debug=debug_backtrace();
throw new InvalidArgumentException(
'Value is not integer in line <'.$debug[0]['line'].'>'
.' type <'.gettype($b).'>'
);
return false;
}
//挿入
if($a===NULL){
$this->arr[]=$b;
}else{
$this->arr[$a]=$b;
}
return true;
}
//値が存在するか ArrayAccess::offsetExists
public function offsetExists($a){
if($a===NULL){return false;}
return isset($this->arr[$a]);
}
//値を取得 ArrayAccess::offsetGet
public function offsetGet($a){
if($this->offsetExists($a)){
return $this->arr[$a];
}else{
return null;
}
}
//値削除 ArrayAccess::offsetUnset
public function offsetUnset($a){
if($this->offsetExists($a)){
unset($this->arr[$a]);
}
}
//個数カウント Countable::count
public function count(){
return count($this->arr);
}
//イテレータ IteratorAggregate::getIterator
public function getIterator(){
return new ArrayIterator($this->arr);
}
#↓クラスのおわり
}
|
__get()および__set()を実装すると、存在しないプロパティにアクセスした際にそのメソッドが呼び出されます。
http://jp.php.net/manual/ja/language.oop5.overloading.php#language.oop5.overloading.members
intArray.php
1
2
3
4
5
6
7
8
9
10
11
12
13
|
//インスタンス
require_once('intArray.class.php');
$int=new intArray();
//代入
$int[2]=10;
$int->a=20;
//取得
print($int->{2});
print($int['a']);
|
$int->a=10;
と書くと、intArrayクラスにaというプロパティは無いのでintArray::__set('a',10)というメソッドが呼ばれます。
これを利用してオブジェクト的、配列的どっちにでもアクセスできるようになりました。
まあ値の代入はArrayAccess::offsetSet()、ArrayAccess::offsetGet()で実装されているので、__set()、__get()自体はそれらを呼んでるだけという簡単実装です。
以上で、$int['a']=10と値を代入し、$int->aで値を取り出すことが出来ます。
まあ混在させると分かり難いだけなのでどちらかに統一すべきなんですが。
privateなメンバに対しても__set、__getが優先するので$int->arr=10;と書いても大丈夫です。
publicなメンバがあった場合のみ、そちらに対しての上書きが優先されます。
今回はpublicなメンバは存在しないので失敗する可能性はありません。
ちなみに数値で始まるメンバ変数にアクセスする場合、$int->{'1a'}と{}で括ります。
数値だけのメンバならさらに$int->{1}でもアクセスできます。
全くどうでもいいんですが、普通の変数でも${1}と数字だけの変数を作成できます。
激しく気持ち悪い。
PR
トラックバック
トラックバックURL: