zoukankan      html  css  js  c++  java
  • PHP的重载及魔术方法

    首先你要知道什么是php的魔术方法,它不是变魔术的,如果你想学习变魔术来错地方了哦!

    定义:PHP 将所有以 __(两个下划线)开头的类方法保留为魔术方法。所以在定义类方法时,除了上述魔术方法,建议不要以 __ 为前缀。

    作用:利用模式方法可以轻松实现PHP面向对象中重载(Overloading即动态创建类属性和方法)

    其实很多博客主已经写过这些方法了、、、但是我还是要说一遍。。谁让你来听了呢,码这么多字也不容易看完再走吧!

    1.__construct,__destruct
    __constuct构建对象的时被调用;
    __destruct明确销毁对象或脚本结束时被调用;

    class Foo {
    
        private $name;
        private $link;
    
        public function __construct($name) {
            $this->name = $name;
        }
    
        public function __destruct() {
            echo 'Destroying: ', $this->name, PHP_EOL;//PHP_EOL代表php的换行符
        }
    }

    打住,先安利一波重载的定义及使用方法:

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

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

    注意:所有的重载方法都必须被声明为 public

    2.__get、__set、__isset、__unset、__call、__callStatic  //为啥放一起呢?


    __set当给不可访问或不存在属性赋值时被调用
    __get读取不可访问或不存在属性时被调用

    __isset对不可访问或不存在的属性调用isset()或empty()时被调用
    __unset对不可访问或不存在的属性进行unset时被调用

    __call调用不可访问或不存在的方法时被调用
    __callStatic调用不可访问或不存在的静态方法时被调用

    Example #1 使用 __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;
        }
    
    
    
        /**  PHP 5.1.0之后版本 */
        public function __isset($name) 
        {
            echo "Is '$name' set?
    ";
            return isset($this->data[$name]);
        }
    
        /**  PHP 5.1.0之后版本 */
        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 . "
    ";
    ?>

    看完了吗?好好看!


    5.__sleep,__wakeup
    __sleep当使用serialize时被调用,当你不需要保存大对象的所有数据时很有用

    __wakeup当使用unserialize时被调用,可用于做些对象的初始化操作

    <?php
    class Connection 
    {
        protected $link;
        private $server, $username, $password, $db;
        
        public function __construct($server, $username, $password, $db)
        {
            $this->server = $server;
            $this->username = $username;
            $this->password = $password;
            $this->db = $db;
            $this->connect();
        }
        
        private function connect()
        {
            $this->link = mysql_connect($this->server, $this->username, $this->password);
            mysql_select_db($this->db, $this->link);
        }
        
        public function __sleep()
        {
            return array('server', 'username', 'password', 'db');
        }
        
        public function __wakeup()
        {
            $this->connect();
        }
    }
    ?>


    6.__clone
    进行对象clone时被调用,用来调整对象的克隆行为

    <?php
    class SubObject
    {
        static $instances = 0;
        public $instance;
    
        public function __construct() {
            $this->instance = ++self::$instances;
        }
    
        public function __clone() {
            $this->instance = ++self::$instances;
        }
    }
    
    class MyCloneable
    {
        public $object1;
        public $object2;
    
        function __clone()
        {
          
            // 强制复制一份this->object, 否则仍然指向同一个对象
            $this->object1 = clone $this->object1;
        }
    }
    
    $obj = new MyCloneable();
    
    $obj->object1 = new SubObject();
    $obj->object2 = new SubObject();
    
    $obj2 = clone $obj;
    
    
    print("Original Object:
    ");
    print_r($obj);
    
    print("Cloned Object:
    ");
    print_r($obj2);
    
    ?>


    7.__toString
    当一个类被转换成字符串时被调用

    <?php
    class SubObject
    {
        static $instances = 0;
        public $instance;
    
        public function __construct() {
            $this->instance = ++self::$instances;
        }
    
        public function __clone() {
            $this->instance = ++self::$instances;
        }
    }
    
    class MyCloneable
    {
        public $object1;
        public $object2;
    
        function __clone()
        {
          
            // 强制复制一份this->object, 否则仍然指向同一个对象
            $this->object1 = clone $this->object1;
        }
    }
    
    $obj = new MyCloneable();
    
    $obj->object1 = new SubObject();
    $obj->object2 = new SubObject();
    
    $obj2 = clone $obj;
    
    
    print("Original Object:
    ");
    print_r($obj);
    
    print("Cloned Object:
    ");
    print_r($obj2);
    
    ?>

    8.__set_state
    当调用var_export()导出类时,此静态方法被调用。用__set_state的返回值做为var_export的返回值。

    <?php
    
    class A
    {
        public $var1;
        public $var2;
    
        public static function __set_state($an_array) // As of PHP 5.1.0
        {
            $obj = new A;
            $obj->var1 = $an_array['var1'];
            $obj->var2 = $an_array['var2'];
            return $obj;
        }
    }
    
    $a = new A;
    $a->var1 = 5;
    $a->var2 = 'foo';
    
    eval('$b = ' . var_export($a, true) . ';'); // $b = A::__set_state(array(
                                                //    'var1' => 5,
                                                //    'var2' => 'foo',
                                                // ));
    var_dump($b);
    
    ?>

    enmmm,我知道你记不住的。。这么多谁记得住啊,好烦啊、、、别,这还没讲完呢,更多方法请参考PHP的官方文档:http://php.net/manual/zh/,别打我,你自己去看吧,毕竟好东西还是要众乐乐的!了;另外这些代码你最好再编译器中运行一边,不然看完你估计和没看一个样2333 ····  

    作者原创、转载请注明出处

  • 相关阅读:
    SDN课程阅读作业(2)
    2019 SDN上机第4次作业
    第11组 Alpha事后诸葛亮
    第11组 Alpha冲刺(6/6)
    第11组 Alpha冲刺(5/6)
    2019 SDN上机第3次作业
    2019 SDN阅读作业
    第11组 Alpha冲刺(4/6)
    第11组 Alpha冲刺(3/6)
    模式识别和机器学习、数据挖掘的区别与联系(转发)
  • 原文地址:https://www.cnblogs.com/ldw-blogs/p/7764969.html
Copyright © 2011-2022 走看看