PHPむンタビュヌの準備反埩に぀いおのすべおず反埩可胜な擬䌌型に぀いおの少し

圌らがむンタビュヌで難しい質問をするのが奜きなのは秘密ではありたせん。 垞に適切であるずは限らず、珟実ず垞に関連しおいるずは限りたせんが、事実は残っおいたす。 もちろん、質問は議論の䜙地があり、時には䞀芋するず銬鹿げおいるように芋える質問は、実際にあなたが曞いおいる蚀語をどれだけ知っおいるかをチェックするこずを目的ずしおいたす。



そしお、もちろん、面接での質問がどんなに奇劙で䞍正確であっおも、あなたはプログラミングのために支払われる蚀語を知っお、結局準備する必芁がありたす。



画像



䞀連の蚘事の第3郚は、珟代のPHPで最も膚倧な抂念の1぀である反埩、反埩子、反埩可胜゚ンティティに圓おられおいたす。 PHPの開発者の地䜍に察するむンタビュヌのための自己準備に適した、この問題に関する特定の最䜎限の知識を1぀のテキストで削枛しようずしたした。



前の2぀の郚分







PHPの配列



最初から始めたしょう。



PHPには配列がありたす。 PHPの配列は連想的です。぀たり、ペアキヌ、倀を栌玍したす。キヌはintたたはstringである必芁があり、倀はどのタむプでもかたいたせん。



䟋



$arr = ['foo' => 'bar', 'baz' => 42, 'arr' => [1, 2, 3]];
      
      





キヌず倀は、蚘号「=>」で区切られおいたす。 キヌは「むンデックス」ず呌ばれるこずもありたすが、PHPではこれらは同等の甚語です。



PHPの配列では、かなり完党な䞀連の操䜜が定矩されおいたす。



 //    $arr['new'] = 'some value'; //      $arr[] = 'another value'; //      echo $arr['foo']; echo $arr[$bar]; //     unset($arr['foo']); // ""  [$foo, $bar, $baz] = $arr;
      
      





配列を操䜜するための倚くの関数もありたす- 数十、数癟



ただし、おそらくPHPの配列の最も重芁なプロパティは、配列のすべおの芁玠を順番に凊理し、すべおのキヌず倀のペアを順番に取埗する機胜です。



配列の反埩



配列をトラバヌスするプロセスは「反埩」たたは「無効化」ず呌ばれずころで、各ステップ、個々のキヌず倀のペアを取埗するこずも「反埩」です、したがっお配列自䜓は反埩可胜です「反埩」本質。



反埩プロセスの最も単玔な䟋は、もちろん、foreachステヌトメントによっお実装されるゞョむントルヌプです。



 foreach ($arr as $key=>$val) { echo $key . '=>' . $val; echo "\n"; }
      
      





ルヌプヘッダヌのキヌず倀を区切る同じ「=>」蚘号に泚意しおください。



しかし、PHPはどのように理解したすか-ルヌプの特定のステップで配列のどの芁玠を取るか 次に取るのはどれですか そしおい぀停止するのか



この質問に答えるには、各配列に存圚するいわゆる「内郚ポむンタヌ」の存圚に泚意する必芁がありたす。 この䞍可芖のポむンタは「珟圚の」芁玠を指し、さらに1ステップ移動できたす-次の芁玠に移動するか、最初の芁玠に再床リセットしたす。



PHPの内郚ポむンタヌを盎接操䜜するには、䟋を䜿甚しお最も簡単に孊習できる関数がありたす。



 $arr = [1, 2, 3]; //   ,      reset($arr); // key()    ,     ,  null         while ( null !== ($key = key($arr)) ) { // current()    ,      echo $key . '=>' . current($arr); echo "\n"; // next()         next($arr); }
      
      





䞎えられたコヌド䟋が実際に以前に䜿甚されたforeachルヌプず同等であり、foreachがreset、key、current、next関数の構文シュガヌのようなものであるこずは簡単にわかりたすそしおendおよびprev -逆順で怜玢を敎理したす。



このステヌトメントは、PHP 7より前は真実でしたが、珟圚はそうではありたせん-foreachルヌプは、reset、next、およびその他の反埩関数ず同じ内郚ポむンタヌを䜿甚しお停止したため、䜍眮の倉曎を停止したした。



小蚈



したがっお、PHPの配列の繰り返しがどのように機胜するかを芁玄するには





このようなデバむスを䜿甚するず、ルヌプ内で配列芁玠を列挙の繰り返しを敎理できたす。 ただし、foreachルヌプは䌌おいたすが、reset、key、currentなどの関数ず同じ内郚ポむンタヌでは機胜せず、独自のロヌカルルヌプで機胜するこずを理解するこずが重芁です。サむクルのために。



オブゞェクトを反埩凊理する



配列のようなオブゞェクトは、反埩可胜な゚ンティティです。 オブゞェクトは、このコンテキストで衚瀺されるプロパティによっおクロヌルされ、プロパティ名はキヌずしお機胜したす。



 class Foo { public $first = 1; public $second = 2; protected $third = 3; public function iterate() { foreach ($this as $key => $value) { echo $key . '=>' . $value; echo "\n"; } } } $foo = new Foo; foreach ($foo as $key => $value) { echo $key . '=>' . $value; echo "\n"; } /*   first=>1 second=>2 */ $foo->iterate(); /*   first=>1 second=>2 third=>3 */
      
      





ただし、そのような反埩は、その目に芋える特性に埓っお、倚くの堎合完党に圹に立たない。 最も䞀般的な䟋は、内郚の安党なストアに倀のセットを栌玍するオブゞェクトです。 たずえば、次のように



 class Storage { protected $storage = []; public function set($key, $val) { $this->storage[$key] = $val; } public function get($key) { return $this->storage[$key]; } }
      
      





パブリックプロパティを持たないこのようなオブゞェクトの反埩を敎理する方法は そしお、ある皮のカスタム非暙準アルゎリズムを䜿甚しお䞀般的に反埩を敎理する方法は



むテレヌタむンタヌフェむス



独自の反埩アルゎリズムを実装するために、PHPたたはSPLは、5぀のメ゜ッドで構成される特別なIteratorむンタヌフェヌスを提䟛したす。



 //       public function current(); //       public function key(); //    ""    public function next(): void; //    ""    public function rewind(): void; //    -      ? public function valid(): bool
      
      





クラスはこれらのメ゜ッドを実装する必芁があり、実装されたアルゎリズムに埓っおforeachルヌプを䜿甚しおこのクラスのオブゞェクトを反埩する機䌚が埗られたす。



ここでむテレヌタむンタヌフェむスメ゜ッドの説明で蚀及されおいるNB "ポむンタ"は、実際に存圚する配列の内郚ポむンタずは察照的に、玔粋な抜象化です。 この抜象化の実装方法はナヌザヌによっお異なりたす。結果のみが重芁です。たずえば、rewindおよびcurrentメ゜ッドの連続呌び出しは、最初の芁玠の倀を返す必芁がありたす。



Iteratorむンタヌフェヌスを実装する最も簡単な䟋
 class Example implements Iterator { protected $storage = []; public function set($key, $val) { $this->storage[$key] = $val; } public function get($key) { return $this->storage[$key]; } public function current() { return current($this->storage); } public function key() { return key($this->storage); } public function next(): void { next($this->storage); } public function rewind(): void { reset($this->storage); } public function valid(): bool { return null !== key($this->storage); } } $test = new Example; $test->set('foo', 'bar'); $test->set('baz', 42); foreach ($test as $key => $val) { echo $key . '=>' . $val; echo "\n"; }
      
      







TraversableおよびIteratorAggregate



厳密に蚀えば、Traversableむンタヌフェむスを䜿甚するず、foreachを䜿甚しお反埩凊理を行うこずができ、Iteratorがその埌継です。 Traversableの機胜は、盎接実装できない䞀皮の「抜象むンタヌフェヌス」ため、アプリケヌションでIteratorむンタヌフェヌスたたはその「匟」IteratorAggregateを䜿甚する必芁がありたす。 圌に぀いお話したしょう。



SPLには、むテレヌタヌオブゞェクトで他の゚ンティティ配列などをラップできるいく぀かの組み蟌みむテレヌタヌクラスが含たれおいたす。



 $iterator = new ArrayIterator([1, 2, 3]); foreach ($iterator as $key => $val) { // ... }
      
      





このような既補のむテレヌタラッパヌのリストは非垞に倧きく、DirectoryIterator指定されたディレクトリ内のファむルのリストを反埩凊理、RecursiveArrayIteratorネストされた配列の再垰的トラバヌス、FilterIterator䞍芁な倀の拒吊によるトラバヌス、およびその他の倚数の有甚なクラスが含たれたす 。



既補のむテレヌタヌずIteratorAggregateむンタヌフェヌスを䜿甚するず、独自のむテレヌタヌクラスの䜜成を倧幅に簡玠化できたす。 したがっお、䞊蚘のネタバレの䞋にある非垞に長いクラスは、次のようなものに枛らすこずができたす。



 class Example implements IteratorAggregate { protected $storage = []; public function set($key, $val) { $this->storage[$key] = $val; } public function get($key) { return $this->storage[$key]; } public function getIterator(): Traversable { return new ArrayIterator($this->storage); } }
      
      





-結果は、Iteratorむンタヌフェヌスの実装ず同じになりたす。



ゞェネレヌタヌはどうですか



もちろんです。 foreachでそれらを䜿甚したす



 class Generator implements Iterator
      
      





ただし、ゞェネレヌタヌは別の蚘事のトピックです。 それたでの間、ゞェネレヌタヌのメカニズムに魔法は䜕もないず蚀うだけで十分です。同じIteratorむンタヌフェヌスが反埩に䜿甚されたす。 1぀の「but」を陀いお、反埩が既に開始されおいる堎合、ゞェネレヌタヌを「最初に巻き戻す」こずはできたせん。rewindメ゜ッドを呌び出すず䟋倖がスロヌされたす。



反埩可胜タむプ



PHP 7.1より前には、奇劙な状況がありたした。 䞀方には、IteratorたたはIteratorAggregateを介しおTraversableを実装する反埩可胜なオブゞェクトがありたした。 同じメカニズムを䜿甚するのず同じ偎にゞェネレヌタヌがありたした。 たた、反察偎には配列があり、オブゞェクトの可芖プロパティに察する「ネむティブ」反埩がありたす。 実際、同じ動䜜をするが共通点のない2皮類の反埩可胜な゚ンティティがありたした。



7.1では、最終的にこの䞍敎合が解消され、別の「疑䌌型」たたはむしろカスタム型が「反埩可胜」になりたした。



PHPでtype挔算子が衚瀺されるのをい぀か埅぀ず、iterableの定矩は次のように蚘述できたす。



 type iterable = array | Traversable;
      
      





この型は、配列ずすべおのTraversable子孫を組み合わせ、foreachを䜿甚しお反埩できる倀の型を瀺したす。



 function doSomething(iterable $it) { foreach ($it as $key=>$val) { // do something } }
      
      





そしお、それは䜕ですか



このタむプチャヌトは次のずおりです。



 iterable ---> array --> Traversable ---> Iterator --> IteratorAggregate --> Generator
      
      





衚瀺可胜なプロパティに応じおネむティブな反埩を蚱可するオブゞェクト「オブゞェクトだけ」タむプは、反埩可胜なタむプにただ含たれおいないこずに泚意しおください。 しかし、そのようなオブゞェクトを反埩凊理するこずの実甚的な䟡倀はそれほど倧きくないため、動揺する理由はありたせん...



他に読むものは䜕ですか





むンタビュヌず職堎での成功



All Articles