zoukankan      html  css  js  c++  java
  • 魔术方法

     

    特征,系统自定义的函数方法,都以__开头,自动被调用,可被继承,不可以自己定义,不能被static修饰除了__callStatic()

    __construct() __destruct() __call() __callStatic() __get() __set() __isset() __unset() __sleep() __wakeup() __toString() __invoke() __set_state() __clone()  __debugInfo() 等方法在 PHP 中被称为"魔术方法"Magic methods)。在命名自己的类方法时不能使用这些方法名,除非是想使用其魔术功能。

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

    __toString() 

    public string __toString ( void )

    __toString() 方法用于一个类被当成字符串时应怎样回应。例如 echo $obj; 应该显示些什么。此方法必须返回一个字符串,否则将发出一条 E_RECOVERABLE_ERROR 级别的致命错误。

     

    示例1

    <?php
    // Declare a simple class
    class  TestClass
    {
        public  $foo ;
    
        public function  __construct ( $foo ) 
        {
             $this -> foo  =  $foo ;
        }
    
        public function  __toString () {
            return  $this -> foo ;
        }
    }
    
    $class  = new  TestClass ( 'Hello' );
    echo  $class ;
    ?> 

    以上例程会输出:

    Hello

    需要指出的是在 PHP 5.2.0 之前,__toString() 方法只有在直接使用于 echo  print 时才能生效。PHP 5.2.0 之后,则可以在任何字符串环境生效(例如通过 printf() ,使用 %s 修饰符),但不能用于非字符串环境(如使用 %d 修饰符)。自 PHP 5.2.0 起,如果将一个未定义 __toString() 方法的对象转换为字符串,会产生 E_RECOVERABLE_ERROR 级别的错误。

    方法重载

    public mixed __call ( string $name , array $arguments )

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

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

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

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

    __call()__callStatic()用法一样,只是__callStatic()的方法为静态方法

     

    属性重载

     

    public void __set ( string $name , mixed $value )

     

    public mixed __get ( string $name )

     

    public bool __isset ( string $name )

     

    public void __unset ( string $name )

     

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

     

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

     

    当对不可访问属性调用 isset()  empty() 时,__isset() 会被调用。

     

    当对不可访问属性调用 unset() 时,__unset() 会被调用。

     

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

     

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

     

    Note:

     

    因为 PHP 处理赋值运算的方式,__set() 的返回值将被忽略。类似的, 在下面这样的链式赋值中,__get() 不会被调用: 

     

    $a = $obj->b = 8;

     

    Note:

     

    在除 isset() 外的其它语言结构中无法使用重载的属性,这意味着当对一个重载的属性使用 empty() 时,重载魔术方法将不会被调用。

     

    为避开此限制,必须将重载属性赋值到本地变量再使用 empty() 

     

    复制

     

    在多数情况下,我们并不需要完全复制一个对象来获得其中属性。但有一个情况下确实需要:如果你有一个 GTK 窗口对象,该对象持有窗口相关的资源。你可能会想复制一个新的窗口,保持所有属性与原来的窗口相同,但必须是一个新的对象(因为如果不是新的对象,那么一个窗口中的改变就会影响到另一个窗口)。还有一种情况:如果对象 A 中保存着对象 B 的引用,当你复制对象 A 时,你想其中使用的对象不再是对象 B 而是 B 的一个副本,那么你必须得到对象 A 的一个副本。

     

    对象复制可以通过 clone 关键字来完成(如果可能,这将调用对象的 __clone() 方法)。对象中的 __clone() 方法不能被直接调用。

     

    $copy_of_object = clone $object;

     

    当对象被复制后,PHP 5 会对对象的所有属性执行一个浅复制(shallow copy)。所有的引用属性 仍然会是一个指向原来的变量的引用。

     

    void __clone ( void )

     

    当复制完成时,如果定义了 __clone() 方法,则新创建的对象(复制生成的对象)中的 __clone() 方法会被调用,可用于修改属性的值(如果有必要的话)。

     

    class City{
    
        protected $name;
        private $area;
    
        function __construct($name, $area){
            $this->name = $name;
            $this->area = $area;
        }
    
        /**
         * __get魔术方法,它是在外部访问该类中不能直接访问的属性时自动被调用
         * 魔术方法都有其默认的定义格式,不能随意的更改
         * 魔术方法不能被添加static静态的修饰符
         * __get魔术方法必须有一个返回值
         * @param $name     它对应的是类中的被声明的属性的名称,格式为字符串
         */
        function __get($name){
    //        echo '我被调用了:'.$name;
            if(isset($this->$name)){
                return $this->$name;
            }else{
                return null;
            }
        }
    
        /**
         * __set魔术方法,在给类中无法直接访问的属性赋值时自动调用
         * @param $name      被赋值的类中的属性名称,字符串格式
         * @param $value     被赋予的值
         */
        function __set($name, $value){
    //        echo '我被调用了:'.$name.'==='.$value;
            /*
             * property_exists  检测类或者对象中是否包含指定名称的属性
             */
            if(property_exists($this, $name)){
                $this->$name = $value;
            }else{
                echo '类中没有对应的属性:'.$name.'<br>';
            }
        }
    
        function __isset($name){
            if(property_exists($this, $name)){
                return isset($this->$name);
            }
        }
        function __unset($name){
    //        echo '需要销毁的属性:'.$name;
            if(property_exists($this, $name)){
                $this->$name = null;
            }else{
                unset($this->$name);
            }
        }
    
    
        /**
         * __toString魔术方法,当使用字符串的方式来输出类的对象时被自动调用
         * 它要求必须返回一个字符串结果
         */
        function __toString(){
    
            return '<br>城市名称:'.$this->name.',面积:'.$this->area;
        }
    
        /**
         * __clone魔术方法,当类的对象被克隆时自动被调用
         * 默认的克隆时浅克隆模式
         * 该方法可以实现克隆时修改某些属性的值
         */
        function __clone(){
            echo '<br>调用了clone的魔术方法<br>';
            $this->area = '3333平方公里';
        }
    
    }
    
    
    
    $city = new City('成都', '3000平方公里');
    //__clone()
    //$city2 = clone $city;
    //var_dump($city);
    //echo '<br>';
    //var_dump($city2);
    //echo '<br>';
    
    //__toString()
    //var_dump($city);
    //echo '<br>';
    //print_r($city);
    //echo '<br>';
    //print $city;
    //echo $city;
    
    //__call()
    //$city->test();
    //$city->test1('哈哈哈哈');
    //$city->test2(100,200);
    
    // get()
    //echo '名称:'.$city->name.'<br>';
    //echo '面积:'.$city->area.'<br>';
    //echo '人口:'.$city->people.'<br>';
    //echo '<br>';
    //set()
    //$city->name = '重庆';
    ////$city->people = '15000000';
    
    //unset()
    //unset($city->name);
    //echo '名称:'.$city->name.'<br>';
    //echo '面积:'.$city->area.'<br>';
    //echo '人口:'.$city->people.'<br>';
    //echo '<br>';
    //var_dump($city);
    
    //根据$test是否有值使用isset
    //$test = false;
    //if(isset($test)){ echo 'OK';}
    
    //判断是否有people这个变量
    //if(isset($city->people)){
    //    echo '====有值====';
    //}else{
    //    echo '====没有获取到值====';
    //}

     

     

     

     

  • 相关阅读:
    服务级后门自己做——创建服务
    使用Win32创建串口通讯程序
    LoadImage with resource 出现未定义
    direct path write等待事件
    enq: TX row lock/index contention、allocate ITL等待事件
    enq: TT contention等待事件
    enq: TM contention等待事件
    enq: RO fast object reuse等待事件
    direct path write temp等待事件
    enq: US contention等待事件
  • 原文地址:https://www.cnblogs.com/chenduzizhong/p/7219571.html
Copyright © 2011-2022 走看看