忍者ブログ
[PR]
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。



2017/07/23 19:52 |
PHP1-66:オブジェクトに配列でアクセスするさらに続き

前回の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
<?php
    
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 &lt;'.$debug[0]['line'].'&gt;'
                .' type &lt;'.gettype($b).'&gt;'
            );
            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
<?php
    
    //インスタンス
        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


2009/04/10 19:01 | Comments(0) | TrackBack(0) | PHP

トラックバック

トラックバックURL:

コメント

コメントを投稿する






Vodafone絵文字 i-mode絵文字 Ezweb絵文字 (絵文字)



<<PHP1-67:オブジェクトに配列でアクセスするまたまた続き | HOME | PHP1-65:オブジェクトに配列とforeachでアクセスする続き>>
忍者ブログ[PR]