PHP 의 7 개의 미리 정 의 된 인 터 페 이 스 를 자세히 설명 합 니 다.

1.Traversable(옮 겨 다 니 기)인터페이스
이 인 터 페 이 스 는 클래스 에 의 해 직접 실현 되 지 않 습 니 다.일반 클래스 를 직접 써 서 이 인 터 페 이 스 를 옮 겨 다 니 면 치 명 적 인 오 류 를 직접 보고 할 수 있 습 니 다.Iterator(교체 기 인터페이스)나 Iterator Aggregate(취 합 교체 기 인터페이스)를 사용 하여 이 루어 지 는 것 을 알려 줍 니 다.이 두 인 터 페 이 스 는 나중에 소개 합 니 다.모든 일반적인 상황 에서 우 리 는 이 종 류 를 foreach 로 옮 겨 다 닐 수 있 는 지 판단 하 는 데 만 사용 합 니 다.

class Test implements Traversable
{
}
         ,           :
Fatal error: Class Test must implement interface Traversable as part of either Iterator or
IteratorAggregate in Unknown on line 0
위의 대체적인 뜻 은 이 인 터 페 이 스 를 실현 하려 면 Iterator 나 Iterator Aggregate 와 함께 정확 한 방법 을 실현 해 야 한 다 는 것 이다.우리 가 foreach 를 사용 하여 옮 겨 다 닐 수 있 는 지 판단 하려 면 traversable 의 인 스 턴 스 인지 판단 해 야 한다.

class Test
{
}
$test = new Test;
var_dump($test instanceOf Traversable);
2.Iterator(교체 기)인터페이스
교체 기 인터페이스 가 실제 적 으로 실현 되 는 원 리 는 포인터 와 유사 한 이동 이다.우리 가 종 류 를 쓸 때 해당 하 는 5 가지 방법:key(),current(),next(),rewind(),valid()를 실현 하면 데이터 의 교체 이동 을 실현 할 수 있다.구체 적 으로 다음 코드 를 볼 수 있다.

<?php
    class Test implements Iterator
    {
        private $key;
        private $val = [
            'one',
            'two',
            'three',
        ];

        public function key()
        {
            return $this->key;
        }

        public function current()
        {
            return $this->val[$this->key];
        }

        public function next()
        {
            ++$this->key;
        }

        public function rewind()
        {
            $this->key = 0;
        }

        public function valid()
        {
            return isset($this->val[$this->key]);
        }
    }

    $test = new Test;

    $test->rewind();

    while($test->valid()) {
        echo $test->key . ':' . $test->current() . PHP_EOL;
        $test->next();
    }
\#\#이 출력 결과:       
0: one
1: two
2: three
이 원 리 를 보면 알 수 있 듯 이 교체 하 는 이동 방식:rewind()->valid()->key()->current()->next()->valid()->key()...->valid();
알 겠 습 니 다.위 에서 이 해 했 습 니 다.Iterator 의 인 터 페 이 스 를 열 었 는데 Traversable(옮 겨 다 니 기)인 터 페 이 스 를 실현 한 것 을 발 견 했 습 니 다.다음 에 증명 하 겠 습 니 다.
var_dump($test instanceOf Traversable);
결 과 는 true 로 돌아 와 서 이 종류의 대상 이 옮 겨 다 닐 수 있다 는 것 을 증명 합 니 다.

foreach ($test as $key => $value){
    echo $test->key . ':' . $test->current() . PHP_EOL;
}
이 결 과 는 while 순환 이 이 루어 진 모델 과 같다.
3.Iterator Aggregate(폴 리머 교체 기)인터페이스
취 합 교체 기와 교체 기의 원 리 는 같 습 니 다.다만 취 합 교체 기 는 이미 교체 기 원 리 를 실현 하 였 을 뿐 입 니 다.당신 은 하나의 getIterator()방법 으로 교 체 를 실현 해 야 합 니 다.구체 적 으로 다음 코드 를 보 세 요.

<?php
    class Test implements IteratorAggregate
    {
        public $one = 1;
        public $two = 2;
        public $three = 3;

        public function __construct()
        {
            $this->four = 4;
        }

        public function getIterator()
        {
            return new AraayIterator($this);
        }
    }

    $test = (new Test())->getIterator();
    $test->rewind();
    while($test->valid()) {
        echo $test->key() . ' : '  .  $test->current() . PHP_EOL;
        $test->next();
    }

    //      ,         Test            ,  while    ,        getIterator()          ,          ,          key()   。
    //      ,              foreach         ?           

    $test = new Test;
    var_dump($test instanceOf Traversable);

    //     bool true,           foreach     。

    $test = new Test;
  foreach($test as $key => $value) {
     echo $key . ' : ' . $value  .  PHP_EOL;
  }

 //   ,            ,                 ?

 class Test implements IteratorAggregate
 {
    public $data;

    public function __construct()
    {
        $this->data = [''one' =>  1 , 'two' => 2];
    }

    public function getIterator()
    {
        return new AraayIterator($this->data);
    }
 }

 //                   。
4.ArrayAccess(배열 접근)인터페이스
일반적으로,우 리 는 this[name]와 같은 용법 을 볼 수 있 습 니 다.그러나 우 리 는$this 가 하나의 대상 이 고,어떻게 배열 방식 으로 접근 하 는 지 알 고 있 습 니 다.정 답 은 데이터 그룹 액세스 인터페이스 Array Access 를 실현 한 것 입 니 다.구체 적 인 코드 는 다음 과 같 습 니 다.

<?php
    class Test implements ArrayAccess
    {
        public $container;

        public function __construct()
        {
            $this->container = [
                'one' => 1,
                'two' => 2,
                'three'  => 3,
            ];
        }

        public function offsetExists($offset)
        {
            return isset($this->container[$offset]);
        }

        public function offsetGet($offset)
        {
            return isset($this->container[$offset]) ? $this->container[$offset] : null;
        }

        public function offsetSet($offset, $value)
        {
            if (is_null($offset)) {
                $this->container[] = $value;
            } else {
                $this->container[$offset] = $value;
            }
        }

        public function offsetUnset($offset)
        {
            unset($this->container[$offset]);
        }
    }
   $test = new Test;
   var_dump(isset($test['one']));
   var_dump($test['two']);
   unset($test['two']);
   var_dump(isset($test['two']));
   $test['two'] = 22;
   var_dump($test['two']);
   $test[] = 4;
   var_dump($test);
   var_dump($test[0]);

   //                            

   class Test implements ArrayAccess
   {
        public $name;

        public function __construct()
        {
            $this->name = 'gabe';
        }

        public function offsetExists($offset)
        {
            return isset($this->$offset);
        }

        public function offsetGet($offset)
        {
            return isset($this->$offset) ? $this->$offset : null;
        }

        public function offsetSet($offset, $value)
        {
            $this->$offset = $value;
        }

        public function offsetUnset($offset)
        {
            unset($this->$offset);
        }
   }

  $test = new Test;
  var_dump(isset($test['name']));
  var_dump($test['name']);
  var_dump($test['age']);
  $test[1] = '22';
  var_dump($test);
  unset($test['name']);
  var_dump(isset($test['name']));
  var_dump($test);
  $test[] = 'hello world';
  var_dump($test);
5.Serializable(직렬 화)인터페이스
일반적으로 우리 클래스 에서 마술 방법,sleep(),wakeup()을 정의 하면 serialize()를 진행 할 때 sleep()의 마술 방법 을 먼저 호출 합 니 다.우 리 는 하나의 배열 로 돌아 가 대상 의 어떤 속성 을 직렬 화 하 는 지 정의 합 니 다.마찬가지 로 우 리 는 반 직렬 화 unserialize()방법 을 호출 할 때,또한 먼저 사용 하 는 wakeup()마술 방법 도 초기 화 할 수 있 습 니 다.예 를 들 어 대상 의 속성 을 할당 하 는 등 작업 을 할 수 있 습 니 다.그러나 이 클래스 가 직렬 화 인 터 페 이 스 를 실현 한다 면 우 리 는 serialize()방법 과 unserialize()방법 을 실현 해 야 한다.동시에 sleep()와 wakeup()두 가지 마술 방법 은 동시에 지원 되 지 않 을 것 이다.구체 적 인 코드 는 다음 과 같다.

<?php
    class Test
    {
        public $name;
        public $age;

        public function __construct()
        {
            $this->name = 'gabe';
            $this->age = 25;
        }

        public function __wakeup()
        {
            var_dump(__METHOD__);
            $this->age++;
        }

        public function __sleep()
        {
            var_dump(__METHOD__);
            return ['name'];
        }
    }

    $test = new Test;
    $a = serialize($test);
    var_dump($a);
    var_dump(unserialize($a));

    //       ,         

   class Test implements Serializable
   {
    public $name;
    public $age;

    public function __construct()
    {
        $this->name = 'gabe';
        $this->age = 25;
    }

    public function __wakeup()
    {
        var_dump(__METHOD__);
        $this->age++;
    }

    public function __sleep()
    {
        var_dump(__METHOD__);
        return ['name'];
    }

    public function serialize()
    {
        return serialize($this->name);
    }

    public function unserialize($serialized)
    {
        $this->name = unserialize($serialized);
        $this->age = 1;
    }
}
$test = new Test;
$a = serialize($test);
var_dump($a);
var_dump(unserialize($a));
6.Closure 클래스
익명 함 수 를 대표 하 는 클래스 에 사 용 됩 니 다.익명 함 수 는 모두 Closure 폐쇄 류 의 인 스 턴 스 입 니 다.이 클래스 에는 주로 두 가지 방법 이 있 습 니 다.bindto()와 bind()는 소스 코드 를 보면 두 가지 방법 이 서로 다른 길 로 돌아 가 는 것 을 발견 할 수 있 습 니 다.bind()는 정적 방법 일 뿐 구체 적 인 용법 은 다음 과 같 습 니 다.

<?php
    $closure = function () {
        return 'hello world';
    }

    var_dump($closure);
    var_dump($closure());
위의 예 를 통 해 첫 번 째 로 인쇄 된 것 은 Closure 의 인 스 턴 스 이 고 두 번 째 는 익명 함수 가 되 돌아 오 는 hello World 문자열 을 인쇄 하 는 것 임 을 알 수 있 습 니 다.다음은 이 익명 류 를 사용 하 는 방법 입 니 다.이 두 가지 방법의 목적 은 모두 익명 함 수 를 한 종류 에 연결 하여 사용 하 는 것 입 니 다.
bindTo()

<?php
namespace demo1;
    class Test {
        private $name = 'hello woeld';
    }

    $closure = function () {
        return $this->name;
    }

    $func = $closure->bindTo(new Test);
    $func();
    //               ,           
    //           
    $func = $closure->bindTo(new Test, Test::class);
    $func();

namespace demo2;
    class Test
    {
        private statis $name = 'hello world';
    }

    $closure = function () {
        return self::$name;
    }
    $func = $closure->bindTo(null, Test::class);
    $func();
bind()

<?php
namespace demo1;
class Test
{
    private  $name = 'hello world';
}

$func = \Closure::bind(function() {
    return $this->name;
}, new Test, Test::class);

$func();

namespace demo2;
class Test
{
    private static  $name = 'hello world';
}

$func = \Closure::bind(function() {
    return self::$name;
}, null, Test::class);

$func()
7.Generator(생 성기)
Generator 는 Iterator 를 실 현 했 지만 그 는 계승 되 지 못 하고 인 스 턴 스 도 생 성 했다.Iterator 를 실현 한 이상 앞에서 소개 한 바 와 같이 Iterator 와 같은 기능 을 가지 게 되 었 습 니 다.rewind->valid->current->key->next.........................................................yield 는 한 번 순환 하 는 중계 역 과 같 습 니 다.이번 활동 궤적 을 기록 하고 Generator 의 인 스 턴 스 를 되 돌려 줍 니 다.Generator 의 장점 은 우리 가 빅 데 이 터 를 옮 겨 다 니 거나 큰 파일 의 읽 기와 쓰 기 를 사용 해 야 하 는데 우리 의 메모리 가 부족 한 상황 에서 메모리 에 대한 소 모 를 크게 줄 일 수 있다 는 것 이다.왜냐하면 전통 적 인 옮 겨 다 니 는 데 이 터 는 모든 데 이 터 를 되 돌려 주기 때문이다.이 데 이 터 는 메모리 에 존재 하고 yield 는 현재 값 만 되 돌려 준다.그러나 우리 가 yield 를 사용 할 때,사실 그 중 에 기억 체 를 처리 하 는 과정 이 있 기 때문에 사실은 시간 으로 공간 을 바 꾸 는 방법 이다.

<?php
$start_time = microtime(true);
function xrange(int $num){
    for($i = 0; $i < $num; $i++) {
        yield $i;
    }
}
$generator = xrange(100000);
foreach ($generator as $key => $value) {
    echo $key . ': ' . $value . PHP_EOL;
}
echo 'memory: ' . memory_get_usage() . ' time: '. (microtime(true) - $start_time);
출력:
memory: 388904 time: 0.12135100364685

<?php
$start_time = microtime(true);
function xrange(int $num){
    $arr = [];
    for($i = 0; $i < $num; $i++) {
        array_push($arr, $i);
    }
    return $arr;
}
$arr = xrange(100000);
foreach ($arr as $key => $value) {
    echo $key . ': ' . $value . PHP_EOL;
}
echo 'memory: ' . memory_get_usage() . ' time: '. (microtime(true) - $start_time);
출력:
memory: 6680312 time: 0.10804104804993
이상 은 PHP 의 7 개의 미리 정 의 된 인터페이스 에 대한 상세 한 내용 입 니 다.PHP 의 7 개의 미리 정 의 된 인터페이스 에 대한 자 료 는 다른 관련 글 을 주목 하 십시오!

좋은 웹페이지 즐겨찾기