zoukankan      html  css  js  c++  java
  • [学习]php 重载

    php 重载

    官方手册上的评论里不推荐在生产环境使用重载:不利于多人协作,代码可维护性变差,容易导致不可预料的错误等。

    重载分为属性重载和方法重载。

    重载的作用是动态的创建类属性和方法,通过php内置的专用的魔术方法实现。

    属性重载用到的魔术方法:

    • public __set(string $name, mixed $value):void
    • public __get(string $name):mixed
    • public __isset(string $name):bool
    • public __unset(string $name):void

    方法重载用到的魔术方法:

    • public __call(string $name, array $arguments):mixed
    • public static __callStatic(string $name, array $arguments):mixed

    属性重载

    属性发生重载的情形:

    • 通过类实例化的对象访问未在类中声明的属性(此时在类中声明的魔术方法会被调用)
    • 在类的内部通过$this访问未声明过的属性(此时在类中声明的魔术方法会被调用)

    重载对于privateprotected属性不起作用,对于已经在类中声明过的public属性也不起作用。

    对于在类中声明过的privateprotected属性,如果通过类的实例对象访问同名属性,相当于重新创建了一个属性。

    通过代码验证:

    // php 版本5.6.9
    class Test {
        private $data = array();
        public $name = "test";
        private $age = 12;
        protected $height = 180;
    
        // 魔术方法
        public function __set($key,$val) {
            echo "set {$key} to {$val}. 
    ";
            $this->data[$key] = $val;
        }
    
        public function __get($key) {
            echo "Get {$key}. 
    ";
            if(array_key_exists($key,$this->data)) {
                return $this->data[$key];
            }
            return null;
        }
    
        public function __isset($key) {
            echo "Check {$key} is set. 
    ";
            return isset($this->data[$key]);
        }
    
        public function __unset($key) {
            echo "Unset {$key}. 
    ";
            unset($this->data[$key]);
        } 
    
        function getAge() {
            return $this->age;
        }
        function getHeight() {
            return $this->height;
        }
        function getQ() {
            return $this->q;
        }
        function getName() {
            return $this->name;
        }
    }
    
    $t = new Test();
    

    通过实例对象/$this访问未声明的属性:

    $t->getQ(); // Get q.
    $t->q; // Get q.
    $t->q = 123; // set q to 123.
    echo $t->getQ()."
    "; // Get q.  123
    

    访问已声明过的public属性:

    $t->name; // 没有打印输出 魔术方法没有调用
    $t->getName(); // 没有打印输出 魔术方法没有调用
    

    访问privateprotected属性:

    echo $t->getAge()."
    "; // 12 魔术方法没有调用 
    echo $t->getHeight()."
    "; // 180 魔术方法没有调用
    $t->age = 123; // set age to 123.
    $t->height = 456; // set height to 456.
    echo $t->getAge()."
    "; // 12 魔术方法没有调用 虽然通过$this访问,但取的值不是123
    echo $t->getHeight()."
    "; // 180 魔术方法没有调用 虽然通过$this访问,但取的值不是456
    

    方法重载

    在对象中调用一个不可访问方法(包括未在类中声明的方法,privateprotected方法)时, __call(string $name, array $arguments) 会被调用。
    如果通过实例对象调用了在类中声明过的同名的privateprotected方法,那么相当于新建了一个同名的方法调用,跟原来的privateprotected方法没有关系,原来的privateprotected方法也不受影响。

    在静态上下文中调用一个不可访问方法时,__callStatic(string $name, array $arguments) 会被调用。

    这里的静态上下文有多种情形:

    // php 版本5.6.9
    class MethodTest 
    {
        public function __call($name, $arguments) 
        {
            // 注意: $name 的值区分大小写
            echo "Calling object method '$name' "
                 . implode(', ', $arguments). "
    ";
        }
    
        public static function __callStatic($name, $arguments) 
        {
            // 注意: $name 的值区分大小写
            echo "Calling static method '$name' "
                 . implode(', ', $arguments). "
    ";
        }
        private function t() {
            echo "t function call. 
    ";
        }
        protected function tt() {
            echo "tt function call. 
    ";
        }
        static function ttt() {
            echo "ttt function call. 
    ";
        }
    
        function aaa() {
            MethodTest::tee();
        }
        static function bbb() {
            static::tee();
            self::tee();
        }
    }
    
    $obj = new MethodTest;
    

    情形一:

    $obj->runTest('in object context');
    
    MethodTest::runTest('in static context'); // 直接通过类名加双冒号调
    

    情形二:

    MethodTest::aaa(); // 情形二本质上还是情形一
    

    情形三:

    $obj->bbb(); // 在静态方法中
    

    $name 参数是要调用的方法名称。$arguments 参数是一个枚举数组,包含着要传递给方法 $name 的参数。

  • 相关阅读:
    洛谷—— P2234 [HNOI2002]营业额统计
    BZOJ——3555: [Ctsc2014]企鹅QQ
    CodeVs——T 4919 线段树练习4
    python(35)- 异常处理
    August 29th 2016 Week 36th Monday
    August 28th 2016 Week 36th Sunday
    August 27th 2016 Week 35th Saturday
    August 26th 2016 Week 35th Friday
    August 25th 2016 Week 35th Thursday
    August 24th 2016 Week 35th Wednesday
  • 原文地址:https://www.cnblogs.com/fogwind/p/15195883.html
Copyright © 2011-2022 走看看