• PHP重载,不一样的重载


    PHP所提供的重载(overloading)是指动态地创建类属性和方法。我们是通过魔术方法(magic methods)来实现的。

    当调用当前环境下未定义或不可见的类属性或方法时,重载方法会被调用。接下来将使用不可访问属性(inaccessible properties)不可访问方法(inaccessible methods)来称呼这些未定义或不可见的类属性或方法。

    注意:

    1.所有的重载方法都必须被声明为 public

    2.这些魔术方法的参数都不能通过引用传递

    3.PHP中的重载与其它绝大多数面向对象语言不同。传统的重载是用于提供多个同名的类方法,但各方法的参数类型和个数不同

     

    一、属性重载

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

    什么情况下为这些方法被调用呢?

    在给不可访问(protected 或 private)或不存在的属性赋值时,__set() 会被调用。

    读取不可访问(protected 或 private)或不存在的属性的值时,__get() 会被调用。

    当对不可访问(protected 或 private)或不存在的属性调用 isset() 或 empty() 时,__isset() 会被调用。

    当对不可访问(protected 或 private)或不存在的属性调用 unset() 时,__unset() 会被调用。

    参数 $name 是指要操作的变量名称。__set() 方法的 $value 参数指定了 $name 变量的值。

     

    属性重载只能在对象中进行。在静态方法中,这些魔术方法将不会被调用。所以这些方法都不能被 声明为 static。将这些魔术方法定义为 static 会产生一个警告。

    使用 __get(),__set(),__isset() 和 __unset() 进行属性重载

    <?php
    class PropertyTest {
         /**  被重载的数据保存在此  */
        private $data = array();
    
     
         /**  重载不能被用在已经定义的属性  */
        public $declared = 1;
    
         /**  只有从类外部访问这个属性时,重载才会发生 */
        private $hidden = 2;
    
        public function __set($name, $value) 
        {
            echo "Setting '$name' to '$value'
    ";
            $this->data[$name] = $value;
        }
    
        public function __get($name) 
        {
            echo "Getting '$name'
    ";
            if (array_key_exists($name, $this->data)) {
                return $this->data[$name];
            }
    
            $trace = debug_backtrace();
            trigger_error(
                'Undefined property via __get(): ' . $name .
                ' in ' . $trace[0]['file'] .
                ' on line ' . $trace[0]['line'],
                E_USER_NOTICE);
            return null;
        }
    
        public function __isset($name) 
        {
            echo "Is '$name' set?
    ";
            return isset($this->data[$name]);
        }
    
        public function __unset($name) 
        {
            echo "Unsetting '$name'
    ";
            unset($this->data[$name]);
        }
    
        /**  非魔术方法  */
        public function getHidden() 
        {
            return $this->hidden;
        }
    }
    
    
    echo "<pre>
    ";
    
    $obj = new PropertyTest;
    
    $obj->a = 1;
    echo $obj->a . "
    
    ";
    
    var_dump(isset($obj->a));
    unset($obj->a);
    var_dump(isset($obj->a));
    echo "
    ";
    
    echo $obj->declared . "
    
    ";
    
    echo "Let's experiment with the private property named 'hidden':
    ";
    echo "Privates are visible inside the class, so __get() not used...
    ";
    echo $obj->getHidden() . "
    ";
    echo "Privates not visible outside of class, so __get() is used...
    ";
    echo $obj->hidden . "
    ";
    ?>

    二、方法重载

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

    在对象中调用一个不可访问方法时,__call() 会被调用。

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

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

    示例1:使用 __call() 和 __callStatic() 对方法重载

    <?php
    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). "
    ";
        }
    }
    
    $obj = new MethodTest;
    $obj->runTest('in object context');
    
    MethodTest::runTest('in static context');
    ?>

    示例2:实现"传统意义上的"方法重载

    <?php
    class OverloadTest {
        public function __call($names, $arg)
        {
           $param = $arg[0];
           $count = count($param);
           switch ($count) {
               case 1:
                   $this->getName1($param);
                   break;
                case 2:
                   $this->getName2($param);
                   break;
               
               default:
                   // code...
                   break;
           }
        }
        
        private function getName1($a)
        {
            echo "this is getName1
    ";
        }
        private function getName2($a)
        {
            echo "this is getName2
    ";
        }
    }
    
     $test = new OverloadTest();
     $test->getName(['id'=>'15']);
     $test->getName(['id'=>'15', 'age'=>'12']);

  • 相关阅读:
    HDU1058Humble Numbers(DP)
    HDU1285确定比赛名次(拓扑排序)
    HDU2602Bone Collector(DP,0/1背包)
    HDU1869六度分离(最短路floyd)
    HDU3342Legal or Not(拓扑)
    Dijkstra不能得到含有负权边图的单源最短路径
    HDU1069Monkey and Banana(DP)
    HDU1176免费馅饼(DP)
    DAG上的动态规划
    网络分析中数据包结构的定义
  • 原文地址:https://www.cnblogs.com/joshua317/p/15478173.html
Copyright © 2020-2023  润新知