[PHP-dev 1507] 新潟アクセス修飾子ってのを作りました

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

[PHP-dev 1507] 新潟アクセス修飾子ってのを作りました

rti-2
始めまして。rtiと申します。
php 5.3.2を改造して、クラスの外から読めるけど書けないアクセス修飾子を実装しました。
http://d.hatena.ne.jp/rti7743/20100520/1274309263


これを利用すると、 getter を書く手間がなくなります。
また、 $obj->getVal() ではなく、 $obj->Val; 形式でアクセスできます。
それでいて、オブジェクトのカプセル化を一切破壊しません。

こんな感じで指定すると、、、

class Human{
   niigata $Age; //これです。クラス外から読めるけど書けない。

   public function
            __construct($age,$name)
   {
       $this->Age = $age;
       //略
   }
};

//コレできても、
echo $HumanObject->Age;

//これはできない
$HumanObject->Age = 100;
// Fatal error: Cannot access niigata property Human::$Age in
// /home/rti/lab/php-5.3.2/a.php on line 13


getter がたくさんあるクラスで利用すると効果は抜群です。


//非新潟のコード
//無意味なgetterの連続
class Human{
   private $Age,$Name,$Address,$Tel;

   public function
            __construct($age,$name)
   {
       $this->Age = $age;
       //略
   }
   public function getAge(){
       return $this->Age;
   }
   public function getName(){
       return $this->Name;
   }
   public function getAddress(){
       return $this->Address;
   }
   public function getTel(){
       return $this->Tel;
   }

};

↓新潟ライズ


//新潟なコード
class Human{
   niigata $Age,$Name,$Address,$Tel; //これ

   public function
            __construct($age,$name)
   {
       $this->Age = $age;
       //略
   }
};


実装は簡単に言うと zend_object_handlers.c の zend_verify_property_access に引数
writable を追加して、
読み込み時は、 public のように振舞って、書き込み時は private のように振舞っています。

static int zend_verify_property_access(zend_property_info
*property_info, zend_class_entry *ce , int writable TSRMLS_DC) /* {{{
*/
{
        switch (property_info->flags & ZEND_ACC_PPP_MASK) {
                case ZEND_ACC_PUBLIC:
                        return 1;
                case ZEND_ACC_PROTECTED:
                        return zend_check_protected(property_info->ce, EG(scope));
                case ZEND_ACC_NIIGATA:
                    if (!writable)
                        {
                                return 1;
                        }
                case ZEND_ACC_PRIVATE:
                        if ((ce==EG(scope) || property_info->ce == EG(scope)) && EG(scope)) {
                                return 1;
                        } else {
                                return 0;
                        }
                        break;
        }
        return 0;
}
_______________________________________________
PHP-dev mailing list
[hidden email]
http://ml.php.gr.jp/mailman/listinfo/php-dev
Reply | Threaded
Open this post in threaded view
|

[PHP-dev 1508] Re: 新潟アクセス修飾子ってのを作りました

komura-2
komura です。

On Sat, 22 May 2010 06:20:44 +0900
rti <[hidden email]> wrote:

> php 5.3.2を改造して、クラスの外から読めるけど書けないアクセス修飾子を実装しました。
> http://d.hatena.ne.jp/rti7743/20100520/1274309263

PHP に新しいアクセス修飾子を追加するという試みは面白いと思います。

一つ疑問に思ったのでお聞きしたいのですが、「クラス外から読めるが、
書けない属性」を作成したい場合、__get() を利用すれば同様の機能が
実装できるように思います。


<?php
// PHP 5.1.0 以降で実行可能
class Human
{
    private $Age, $Name, $Address, $Tel;

    public function __construct( $age, $name )
    {
        $this->Age = $age;
        $this->Name = $name;
    }

    public function __get( $key )
    {
        return isset( $this->$key ) ? $this->$key : NULL;
    }
}

$h = new Human( 20, 'Name' );
// 20 が出力
echo $h->Age;

// アクセス不可
$h->Age = 100;
// PHP Fatal error: Cannot access private property Human::$Age in
// /tmp/test.php on line 21


この例では、__get() メソッドを追加する必要がありますが、大量の getter
メソッドを作成する必要はありません。ただ、__get() メソッドを処理する
必要がある分、速度は遅くなります。

新しい修飾子を定義した方が getter の処理は速くなるように思いますが、
他に新しいアクセス修飾子を導入することによるメリットがあれば教えて
ください。

--
komura <[hidden email]>
_______________________________________________
PHP-dev mailing list
[hidden email]
http://ml.php.gr.jp/mailman/listinfo/php-dev