19
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

SplFixedArrayで"純粋な配列"を作る

Posted at

よく知られているように、PHPには"純粋な配列"がない。array()は連想配列である。
(ここで言う純粋云々は別にポインタとかの話ではなく、用語としてPHPで「配列」と言ってしまうとarray()のことを指すことから、区別のために「純粋な配列」と書いているだけである。)
添え字は整数でなくても文字列が指定できるし、整数であっても順番が保証されていない。

<?php
$a1 = [10,20,30]; //配列っぽい配列
$a2 = [2=>10, 0=>20, 1=>30]; //添え字は整数だが順番が変な配列
$a3 = ['a'=>10, 20, 30]; //添え字に文字列が混じってる

参考:PHP - 配列か連想配列か判定する - Qiita

まあ慣れれば特に気にならないという人もいるかも知れないけど、コードの欠陥を感染が広がる前になるべく見つけたいという静的検査欲求がある人は、何が入っているかよくわからないPHPの配列を嫌うかもしれない。

PHP5.3から導入されたSplFixedArrayは、自動伸長しない配列である。代わりに高速で省メモリであることを謳っている。
PHP: SplFixedArray - Manual

よくよく見ると、SplFixedArrayは数値の添え字しか許さず、順番も守られることから、"純粋な配列"の条件を満たしている。
自動伸長してほしい場合は、offsetSetをオーバーライドすればいける。

<?php
/**
 * 純粋な配列
 *
 */
class Collection extends SplFixedArray
{
  function offsetSet($offset, $value)
  {
    if ($offset === null) {
      $offset = count($this);
      $this->setSize($offset + 1);
    }

    //配列要素の型を固定にしたければ、ここで$valueの型をチェックすればよい

    return parent::offsetSet($offset, $value);
  }
}
<?php
$a1 = new Collection;
$a1[] = 10;
$a1[] = 20;
$a1[] = 30;

//$a1['a'] = 'hoge'; //例外が発生して止まる

おそらくArrayAccessやCountable、IteratorAggregateなどを地道に実装すれば同様のクラスを再現することもできるだろうけれど、SplFixedArrayを使うのが最も高速で簡潔だと思う。

19
20
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?