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 的参数。

  • 相关阅读:
    bzoj:2423: [HAOI2010]最长公共子序列
    bzoj:3994:vijos1949: [SDOI2015]约数个数和
    bzoj4332;vijos1955:JSOI2012 分零食
    bzoj:1726: [Usaco2006 Nov]Roadblocks第二短路
    bzoj:1724: [Usaco2006 Nov]Fence Repair 切割木板
    bzoj:1666: [Usaco2006 Oct]Another Cow Number Game 奶牛的数字游戏
    bzoj:1230: [Usaco2008 Nov]lites 开关灯
    bzoj:1941: [Sdoi2010]Hide and Seek
    bzoj:1699;poj 3264: [Usaco2007 Jan]Balanced Lineup排队
    bzoj 1705;poj 3612:[Usaco2007 Nov]Telephone Wire 架设电话线
  • 原文地址:https://www.cnblogs.com/fogwind/p/15195883.html
Copyright © 2011-2022 走看看