zoukankan      html  css  js  c++  java
  • 面向对象(四)

    前言:这个章节主要分享一些高级的PHP面向对象的知识

    (一) 两种常见的设计模式(单例和工厂模式)

      引言:在PHP中,存在两种常见的设计模式,一个是单例模式,另一个是工厂模式,这两中设计模式,并不是固定的PHP语法,而是广大的开发工作者在长期的开发工作中总结出来的开发经验。

      1.单例模式

    <?php
    //单例模式实现的目标效果是: 无论我们实例化多少次,都只能得到唯一的一个对象(空间)。
    class A{
        private static $_obj;//定义了一个  静态的  私有的  属性
    
        //将构造方法私有化,使得无法在类的外部使用new关键字实例化这个类的对象
        private function __construct(){ 
    
        }
    
        private function __clone(){ 
            
        }
    
        //定义一个共有的  静态的  方法single
        public static function single(){ 
            
            //判断$_obj静态私有属性是否保存了一个本类的对象
            if( empty(self::$_obj) ){//如果$_obj为空,则表示之前没有创建过本类的对象
                self::$_obj = new self;
            }
            return self::$_obj;
        }
    }

      2.工厂模式

    <?php
    
    class Factory{
    
        public static function produce($className){ 
            
            if( $className=='A' ){
            
                include './A.class.php';
    
            }elseif( $className=='B' ){
            
                include './B.class.php';
            }
    
            $obj = new $className;
            return $obj;
        }
    }
    
    $a1 = Factory::produce('A');
    var_dump( $a1 ); echo '<hr/>';
    $b1 = Factory::produce('B');
    var_dump( $b1 ); 

      (二) 对象遍历

       引言:对象和数组本质上同属于复合数据类型,我们可以在程序中可以对数组进行遍历。

       1.默认的对象遍历

    <?php
    
    class A{
        
        public $name='zhangsan';
        public $age=12;
        public $height=1.8;
    }
    
    $a1 = new A;
    var_dump( $a1 ); echo '<hr/>';echo '<hr/>';
    
    //实现使用foreach对对象进行遍历
    foreach( $a1 as $k=>$v ){ 
        
        echo '$k:'; 
        var_dump( $k ); echo '<br/>';
        echo '$v:'; 
        var_dump( $v ); echo '<hr/>';
    }
    //小结:默认的对象遍历,就是逐个的获得对象中的属性(属性名和属性值);

      2.自定义对象遍历

      实现自定义对象遍历的前提:需要实现PHP预定义接口"Iterator"

      自定义对象遍历的概念:当遍历一个对象时,PHP自动按顺序执行预定义接口Iterator中实现的五个方法

    <?php
    
    
    class A implements Iterator{
    
        public $count=0;
    
        public function current(){ 
            echo 'current<br/>'; 
        }
    
        public function key(){ 
            echo 'key<br/>'; 
        }
    
        public function next(){ 
            echo 'next<br/>'; 
        }
    
        public function rewind(){ 
            echo 'rewind<br/>'; 
        }
    
        public function valid(){ 
            
            $this->count++;
    
            if( $this->count<4 ){
                echo 'valid<br/>';
                return true;
            }else{
                return false;
            }
        }
    }
    
    $a1 = new A;
    var_dump( $a1 ); echo '<hr/>';
    
    foreach( $a1 as $k=>$v ){ 
        
        
    }

    小结:
    1. 第一次将会按照 rewind->valid->current->key->next这个顺序执行五个被实现的方法;

    2. 第二次以后会按照 valid->current->key->next这个顺序循环执行4个被实现的方法;

      (三) 对象序列化

      在PHP中,如果我们直接将(PHP八种数据类型)数据写入文件中,那么,除了字符串数据外,其他的数据都将会失真

      概念:对象的序列化就是通过serialize函数将某个对象转换成一个具有固定信息格式的字符串。涉及的函数:serialize(对象) 将对象进行序列化

    <?php
    
    class DirTool{
        public $path;
        public $resource;
        
        public function __construct(){
            $this->path = './dir';
            $this->resource = opendir($this->path);
        }
    }
    
    $d = new DirTool;
    var_dump( $d ); echo '<hr/>';
    
    //将$d对象进行序列化,获得序列化之后的字符串结果
    $str = serialize($d);
    var_dump( $str ); 

    小结:

    1. 经过序列化之后的对象,变成了一个具有一定格式的字符串。

    2. 资源类型的数据即使序列化之后也会失真,所以一般我们在对对象进行序列化的时候,会把资源类型的数据排除在外

      2.__sleep魔术方法

    <?php
    
    class DirTool{
        public $path;
        public $resource;
        
        public function __construct(){
            $this->path = './dir';
            $this->resource = opendir($this->path);
        }
    
        //__sleep魔术方法   当基于该类的对象被序列化的时候,__sleep魔术方法将被触发执行
        public function __sleep(){ 
            //echo 100; 
            return ['path'];//不在数组中的属性名,将会被排除在序列化操作之外
        }
    }
    
    $d = new DirTool;
    var_dump( $d ); echo '<hr/>';
    
    //将$d对象进行序列化,获得序列化之后的字符串结果
    $str = serialize($d);
    var_dump( $str ); 

    小结

    1. PHP不负责定义__sleep魔术方法,只负责调用该魔术方法;

    2. 调用该魔术方法的时机是:当使用serialize函数序列化一个对象时,该类中的__sleep魔术方法将会被触发自动执行;

    3. 在__sleep魔术方法中,可以同return语句指定乃个属性应该参与到序列化的过程中来,不在数组中的属性都将被排除在序列化的过程之外;

     

      (四) 对象的反序列化

      概念:对象的反序列化就是通过unserialize函数将某个对象序列化后的字符串还原回原来的对象。涉及的函数:unserialize(序列化后的字符串) 将对象进行反序列化

    <?php
    
    $str = 'O:7:"DirTool":2:{s:4:"path";s:5:"./dir";s:8:"resource";i:0;}';
    //将序列化后的字符串进行反序列化,还原回对象
    $obj = unserialize($str);
    
    var_dump( $obj ); 

    小结:我们从效果上看,虽然反序列化回了对象,但是找错了所属的类,这是因为在反序列化的过程中,需要有一个条件,那就是,必须存在这个对象的原始类的定义,即要在序列化的同一个php文件中进行

    <?php
    
    class DirTool{
        public $path;
        public $resource;
        
        public function __construct(){
            $this->path = './dir';
            $this->resource = opendir($this->path);
        }
    }
    
    $str = 'O:7:"DirTool":2:{s:4:"path";s:5:"./dir";s:8:"resource";i:0;}';
    //将序列化后的字符串进行反序列化,还原回对象
    $obj = unserialize($str);
    
    var_dump( $obj ); 

    小结:

    1. 我们可以使用unserialize函数对序列化后的字符串结果进行反序列化;

    2. 反序列化有一个前提,在反序列化的过程中,必须存在该对象的原始类的定义,否则将会把还原的对象归到一个系统类__PHP_Incomplete_Class下;

    <?php
    
    class DirTool{
        public $path;
        public $resource;
        
        public function __construct(){
            $this->path = './dir';
            $this->resource = opendir($this->path);
        }
    
        //__wakeup魔术方法
        public function __wakeup(){ 
            $this->resource = opendir($this->path);
        }
    }
    
    //$str = 'O:7:"DirTool":2:{s:4:"path";s:5:"./dir";s:8:"resource";i:0;}';
    $str = 'O:7:"DirTool":1:{s:4:"path";s:5:"./dir";}';
    var_dump(unserialize($str));

    小结

    1. 我们在__wakeup魔术方法中所作的操作,其实就是将之前排除的属性重新进行赋值操作;

    2. PHP不负责定义__wakeup魔术方法,只负责调用该魔术方法;

    3. 调用该魔术方法的时机是:当使用unserialize函数反序列化一个字符串时,该类中的__wakeup魔术方法将会被触发自动执行;

     

      (五) 命名空间

      

    #关键字为namespace
    namespace  空间名; 

    注意事项:命名空间首次定义之前不能有任何PHP非注释代码

      命名空间的使用

    <?php
    
    namespace first;
    
    function f1(){ 
        echo 100; 
    }
    
    namespace second;
    
    function f1($v1){ 
        echo 200; 
    }

    f1();//就近原则,不限定名称访问
    firstf1();// 限定命名空间的访问
    echo '嘿嘿嘿嘿,能看到我么';

      

      命名空间的引入

    //空间的引入,接上一个方法
    use first;
    f1();

    小结 :

      1.命名空间都是在全局空间下的

      2.命名空间如果需要用到另外的空间需要用use引入才可以使用

    IT这条路,当你懂得越多的时候,那么你不懂的也就会越多了.
  • 相关阅读:
    Android中TextView设置下划线
    BottomSheetDialogFragment 如何设置高度和禁止滑动(Kotlin)
    [iOS]使用GCD创建定时器
    [iOS]定时器NSTimer、CADisplayLink的内存管理
    [iOS]dispatch_after()中self和weakself的使用
    [Flutter]在Mac上安装Flutter运行环境
    wx小程序反编译为js代码
    Android | 玩转AppBarLayout,设置scrollFlags滑动属性详解
    玩转微信 | 炫酷的聊天满屏掉爱心系列,赶紧收藏
    Android使用更简单的方式实现滑块拼图验证码功能
  • 原文地址:https://www.cnblogs.com/learningPHP-students2018/p/10201425.html
Copyright © 2011-2022 走看看