• PHP预定义接口


    目录

    引言

    在PHP中有好几个预定义的接口,还挺有用的

    IteratorAggregate(聚合式aggregate迭代器Iterator)
    IteratorAggregate extends Traversable {
    	abstract public Traversable getIterator(void)
    }
    

    这个接口实现了一个功能——创建外部迭代器,具体怎么理解呢,当我们使用foreach对对象进行便遍历的时候,如果没有继承IteratorAggregate接口,遍历的是对象中所有的public属性(只能是public $var这种形式)。要是继承了IteratorAggregate,会使用类中实现的getIterator方法返回的对象,这里要注意返回的一定要是一个Traversable对象或者扩展自Traversable的对象,否则会抛出异常

    //看个例子
    class My{
        private $_data = [
            'a' => '燕睿涛',
            'b' => 'yanruitao',
            'c' => 'LULU',
        ];
        
        public function getIterator()
        {
            return new ArrayIterator($this->_data);
        }
    }
    $obj = new My;
    foreach ($obj as $key => $value) {
        echo "$key => $value
    ";
    }
    //输出结果为空    
    
    class My implements IteratorAggregate {
        private $_data = [
            'a' => '燕睿涛',
            'b' => 'yanruitao',
            'c' => 'LULU',
        ];
    
        public function getIterator()
        {
            return new ArrayIterator($this->_data);
        }
    }
    $obj = new My;
    foreach ($obj as $key => $value) {
        echo "$key => $value
    ";
    }
    //结果:
    a => 燕睿涛
    b => yanruitao
    c => LULU
    

    Countable
    Countable {
    	abstract public int count(void)
    }
    

    这个接口用于统计对象的数量,具体怎么理解呢,当我们对一个对象调用count的时候,如果函数没有继承Countable将一直返回1,如果继承了Countable会返回所实现的count方法所返回的数字,看看下面的例子:

    class CountMe
    { 
        protected $_myCount = 3; 
    
        public function count() 
        { 
            return $this->_myCount; 
        } 
    } 
    
    $countable = new CountMe(); 
    echo count($countable);
    //返回1
    
    class CountMe implements Countable
    { 
        protected $_myCount = 3; 
    
        public function count() 
        { 
            return $this->_myCount; 
        } 
    } 
    
    $countable = new CountMe(); 
    echo count($countable);    
    //返回3
    

    ArrayAccess
    ArrayAccess {
    	abstract public boolean offsetExists(mixed $offset)
        abstract public mixed offsetGet(mixed $offset)
        public void offsetSet(mixed $offset, mixed $value)
        public void offsetUnset(mixed $offset)
    }
    

    这个接口的作用是让我们可以像访问数组一样访问对象,这个怎么说好呢,我猜其实就是php在词法分析的时候如果碰到了数组的方式使用对象,就回去对象中查找是否有实现ArrayAccess如果有的话,进行对应的操作(set、unset、isset、get),这样我们就可以在类里面放置一个array,让类实现数组方式的基本操作,下面看个例子:

    class myObj
    {
    	
    }
    $obj = new myObj;
    $obj['name'];
    //Fatal error: Cannot use object of type myObj as array in 
    
    class myObj implements ArrayAccess 
    {
        public function offsetSet($offset, $value)
        {
            echo "offsetSet : {$offset} => {$value}
    ";
        }
    
        public function offsetExists($offset)
        {
            echo "offsetExists : {$offset}
    ";
        }
    
        public function offsetUnset($offset)
        {
            echo "offsetUnset : {$offset}
    ";
        }
    
        public function offsetGet($offset)
        {
            echo "offsetGet : {$offset}
    ";
        }
    }
    $obj = new myObj;
    $obj[1] = '燕睿涛';
    isset($obj['name']);
    unset($obj['name']);
    $obj['yrt'];
    
    //输出结果:
    offsetSet : 1 => 燕睿涛
    offsetExists : name
    offsetUnset : name
    offsetGet : yrt
    
    class myObj implements ArrayAccess 
    {
        private $_data = [];
        public function offsetSet($offset, $value)
        {
            $this->_data[$offset] = $value;
        }
    
        public function offsetExists($offset)
        {
            return isset($this->_data[$offset]);
        }
    
        public function offsetUnset($offset)
        {
            unset($this->_data[$offset]);
        }
    
        public function offsetGet($offset)
        {
            return $this->_data[$offset];
        }
    }
    
    
    $obj = new myObj;
    $obj['yrt'] = '燕睿涛';
    var_dump($obj['yrt']);
    var_dump(isset($obj['yrt']));
    unset($obj['yrt']);
    var_dump(isset($obj['yrt']));
    var_dump($obj['yrt']);
    
    //输出:
    string(9) "燕睿涛"
    bool(true)
    bool(false)
    Notice: Undefined index: yrt //最后一个会报出Notice
    

    上面的对象只能是基本的数组操作,连遍历都不行,结合之前的IteratorAggregate可以进行foreach:
    class myObj implements ArrayAccess, IteratorAggregate
    {
    private $_data = [];

        public function getIterator()
        {
            return new ArrayIterator($this->_data);
        }
    
        ......
    }
    $obj = new myObj;
    $obj['yrt'] = '燕睿涛';
    $obj[1] = '燕睿涛';
    $obj['name'] = '燕睿涛';
    $obj['age'] = 23;
    
    foreach ($obj as $key => $value) {
        echo "{$key} => {$value}
    ";
    }
    //输出:
    yrt => 燕睿涛
    1 => 燕睿涛
    name => 燕睿涛
    age => 23
    

    Iterator
    Iterator extends Traversable {
        abstract public mixed current(void)
        abstract public scalar key(void)
        abstract public void next(void)
        abstract public void rewind(void)
        abstract public boolean valid(void)
    }
    

    可在内部迭代自己的外部迭代器或类的接口,这是官方文档给出的解释,看着还是不好理解,其实我感觉这个接口实现的功能和trratorAggregate(文档:创建外部迭代器接口,接口直接返回一个迭代器)类似,不过这个在类的定义里面自己实现了,看个例子:
    class myObj implements Iterator{

        private $_data = [];
    
        public function __construct(Array $arr)
        {
            $this->_data = $arr;
        }
    
        public function current()
        {
            return current($this->_data);
        }
    
        public function key()
        {
            return key($this->_data);
        }
    
        public function next()
        {
            next($this->_data);
        }
    
        public function rewind()
        {
            reset($this->_data);
        }
    
        public function valid()
        {
            return $this->key() !== NULL;
        }
    }
    
    $t = [
        'yrt' => '燕睿涛',
        'name' => '燕睿涛',
        false,
        '燕睿涛'
    ];
    $obj = new myObj($t);
    
    foreach ($obj as $key => $value) {
        echo "{$key} => ".var_export($value, true)."
    ";
    }
    //输出:
    yrt => '燕睿涛'
    name => '燕睿涛'
    0 => false
    1 => '燕睿涛'
    

    上面这个参考了鸟哥的一篇文章关于一笔试题(Iterator模式),不过鸟哥的那个判断valid有点瑕疵,当碰到值北来就是false的时候就会截断

    总结

    说了这么多好像还是没有体会到他们的用处,建议看看Yii2的源码,源码里面大量使用了这些东西,看了之后,你会慢慢觉得“哦~好像还真是挺有用的。。。。”


    微信号: love_skills

    越努力,越幸运!越幸运,越努力!

    做上CEO不是梦

    赢取白富美不是梦

    屌丝逆袭不是梦

    就是现在!!加油

  • 相关阅读:
    [Codeforces #494] Tutorial
    [BZOJ 3223] 文艺平衡树
    [P2698][USACO12MAR]花盆Flowerpot
    [Atcoder Regular Contest 061] Tutorial
    [BZOJ 1855] 股票交易
    [BZOJ 1076] 奖励关
    [BZOJ 2298] Problem A
    数据库三大范式
    mybatis插件机制原理
    Mybatis有哪些执行器?
  • 原文地址:https://www.cnblogs.com/iforever/p/4683363.html
Copyright © 2020-2023  润新知