Создание объектно-ориентированного аналога массива в PHP. Часть 2

Stepler, 28.12.2008

В этой статье мы продолжаем улучшать созданный в первой части класс ObjectsArr.

В прошлый раз мы описали базовую функциональность класса, позволяющую управлять своим содержимым. Но в таком виде его использование не является удобным. В этой статье мы это исправим.

Добавляя данные в массив, мы привыкли использовать конструкцию $objArray[key] = value и врядли мы нас устроит текущая альтернатива — $objArray->add(value, key). Так же в текущей реализации невозможно просмотреть массив с помощью конструкции foreach, поэтому если мы добавляем элемент без ключа (ключ будет присвоен автоматически), то мы фактически «теряем» элемент.

К счастью, разработчики PHP позаботились об этом, и предоставили в наше распоряжение различные предопределенные интерфейсы, которые позволяют выполнять несвойственные объектам операции.

Наш класс ObjectsArr будет реализовывать интерфейсы: ArrayAccess, IteratorAggregate и Countable. Также будет создан новый класс ObjectsArrInrerator, реализующий интерфейс Iterator.

Теперь обо всем по порядку:

Интерфейс ArrayAccess — позволяет обращаться к объекту, используя принцип обращения к обычному массиву.

Интерфейс Countable — позволяет применять функцию count к объекту.

Класс ObjectsArrInrerator в связке с интерфейсом IteratorAggregate — позволяет просматривать массив, используя оператор foreach.

Реализация интерфейса ArrayAccess

//обновляем строку инициализации класса
class ObjectsArr implements ArrayAccess {
  //добавляем новые методы
  public function offsetSet($key, $value) {
        $this->add($value, $key);
  }
  public function offsetUnset($key) {
    $this->del($key);
  }
  public function offsetGet($key) {
    return $this->get($key);
    }
  public function offsetExists($key) {
    return $this->exist($key);
  }
  //остальное описание класса …
}

Как вы можете видеть, новые методы являются оберткой уже существующих, но именно с помощью них можно обращаться к объекту, как к массиву. В частности теперь возможно:

  • использовать $objArray[key] = value вместо $objArray->add(value, key)
  • использовать unset($objArray[key]) вместо $objArray->del(key)
  • использовать $objArray[key] вместо $objArray->get(key)
  • использовать isset($objArray[key]) или empty($objArray[key]) вместо $objArray->exist (key)

Реализация интерфейса Countable

//обновляем строку инициализации класса
class ObjectsArr implements ArrayAccess, Countable {
//добавляем новые методы
  public function count() {
    return $this->length();
  }
//остальное описание класса …
}

Как и в предыдущем случае, теперь можно использовать count($objArray) вместо $objArray->length().

Разработка класса ObjectsArrInrerator и  реализация интерфейса IteratorAggregate

Новый класс, который будет использоваться при просмотре объекта в foreach:

class ObjectsArrInrerator implements Iterator {
  private $_list;
  private $_current;
  private $_keys;
  
  function __construct(ObjectsArr $obj) {
    $this->_list = $obj;
    $this->_keys = $this->_list->keys();
  }
  
  function rewind() {
    $this->_current = 0;
  }
  
  function valid() {
    return $this->_current < $this->_list->length();
  }
  
  function key() {
    return $this->_keys[$this->_current];
  }
  
  function next() {
    $this->_current++;
  }
  
  function current() {
    return $this->_list->get($this->_keys[$this->_current]);
  }
}

Готово! Эти методы объяснять думаю не стоит. Названия у них говорят сами за себя. Они будут использоваться конструкцией foreach при просмотре объекта. Если Вам интересна последовательность их вызова, добавьте в каждый из них echo с названием метода, и увидите как foreach «смотрит» наш объект.

И последнее на сегодня:

//обновляем строку инициализации класса
class ObjectsArr implements ArrayAccess, Countable, IteratorAggregate {
  //добавляем новые методы
  function getIterator() {
    return new ObjectsArrInrerator (clone $this);
  }
  //остальное описание класса …
}

Метод getIterator будет вызываться при попытке просмотреть объект через foreach.

В PHP существует сразу встроенный аналог только что созданного нами класса. Это класс ArrayObject. Но попытка изменения объекта в ходе перебора его элементов, может привести к плачевным последствиям. Об этом я написал в комментарии, к предыдущей статье. Избежать такого поведения позволяет передача интератору, не самого просматриваемого объекта, а его копии — return new ObjectsArrInrerator(clone $this).

Тестирование класса ObjectsArr

Осталось только протестировать наш класс. Для тестирования я взял тот же пример, что и в предыдущей статье, чтобы наглядно было видно как изменился наш класс.

$clientsList = new ObjectsArr();
try {
$clientsList['ivan'] = new Client('Ваня'); //Добавляем нового клиента
$clientsList['alexander'] = new Client('Саша'); //Добавляем нового клиента
$clientsList['petr'] = new Client('Петя'); //Добавляем нового клиента

$objIvan = $clientsList['ivan']; //Извлекаем клиента
echo $objIvan; // выведет ->  Клиент - "Ваня"

foreach ($clientsList as $key => $value) { //Просмотр всей коллекции объектов
  echo $key . ' -> ' . $value . "\r\n";
}

unset($clientsList['ivan']); //удаляем клиента

$clientsList['petr'] = new Client('Петр Иванович'); /*перехват исключения, т.к. ключ "petr" уже используется
                                                          выведет -> Ключ "petr" уже используется. */
} catch (Exception $e) {
  echo $e->getMessage();
}

На данный момент все. Мы реализовали еще одно из предъявленных к классу ObjectsArr требований, а именно:

возможность перебора всей коллекции элементов

Использование класса так же стало более удобным. Теперь его трудно отличить от обычного массива.

В следующей — заключительной статье мы добавим механизм заполнения массива при первом обращении к нему.

Подписаться на обновления блога

Вам понравился наш блог, хотите следить за обновлениями? Подпишитесь на RSS рассылку или рассылку по электронной почте. Так же вы можете следить за нами в Twitter.

Категории: PHP | Комментировать

Комментарии (10)

  1. Сергей / 28.12.2008 в 22:59

    Прошу прощения за комментарий не по теме, но не могли бы ли вы настроить свой блог таким образом, чтобы он не пихал в RSS весь пост? Спасибо.

  2. Александр Анатольевич / 29.12.2008 в 02:56

    А можно весь пост, пожалуйста.

  3. Skaizer / 29.12.2008 в 10:06

    Вообще на мой взгляд удобно в ридере читать весь пост сразу. Да и минусом укороченного поста является то, что wordpress урезает все теги, и в rss кидается только чистый текст, никак не отформатированный. Поэтому оставим как есть.

  4. Сергей / 29.12.2008 в 13:19

    @Skaizer
    Это ваше право, конечно, но в случае аггрегации своего фида в группе — я говорю о Планете developers.org.ua (надо заметить, что в целом непонятно каким боком вы относитесь к украинским разработчикам), это выглядит неуважением к читателям.

  5. Skaizer / 29.12.2008 в 14:08

    Вообще, основная цель RSS данного блога — удобство для наших посетителей читать посты в своем ридере, а не агрегация фида на подобных developers.org.ua сайтах.

    И вы правильно заметили, к украинским разработчикам никаким боком мы не относимся ;-), но не видим ничего плохого в том, что они находят наш блог интересным.

    И кстати, в разделе "Планета" не одни наши посты передаются в полном виде, на мой взгляд проще решить проблему на уровне импорта в систему, скажем, ставить ссылку "Читать далее" после 3-го или 4-го предложения в RSS фиде, а не импортировать его целиком. Т.е. это уже задача разработчиков developers.org.ua.

  6. Евгенйи / 21.07.2010 в 11:04

    Сергей, ты дурак чтоль? Удобнее читать полный пост. Неудобно — не читай.

  7. bestsalejewelry.com / 04.07.2015 в 10:18

    This kind of necklaces obviously are extremely well-known on the Paris, france and Nyc runways nowadays, but couple of attain the particular craftsmanship plus strict great this Mauboussin gems. Make sure you credit appropriately when re-posting. The group of most attention to me, nevertheless , is that of jewellery and Work of art offers the particular best. The particular crashing dunes of Winslow Homer’s ‘Light Blue Ocean at Prout’s Neck’ (1893-94) is re-imagined in gemstones and white-colored gold covered around the hand. This is a really special day because it is exactly the same date the grandparents did marry 59 years back in Italia, so we will certainly share exactly the same wedding date. We sketch in your own home in the country and then visit india to do business with the artisans who arranged the gems and provide your styles to life. Your day and night time jewelry design is different. Developed as a shield-shaped amethyst, padded within a managed to graduate domed platinum eagle band arranged with ranges of brilliant-cut diamonds, covered to the within with platnium, signed SABBA, 2013. Actually groceries plus my Well-known superfood powders! All of us handpick the very best of growing jewellery designersyou need to know regarding! Solution? The particular pieces times to the past due 1800s and it is in outstanding condition. Circa 1970s. It really is especially enjoyable for kids — my daugher 2 1/2 absolutely enjoys it. Driehaus’ collection, yet several parts are taken and shown from notable private enthusiasts, including Neil Lane. Nevertheless , whenever Personally i think going in shop, I do therefore early each morning, because I really like the feeling of getting the store in order to myself. I was given the box along with four engagement of somewhat varying colour grades. We’ve selected our twelve preferred pieces within the sale which are not only wonderful jewels yet offer excellent value too.
    bestsalejewelry.com http://www.bestsalejewelry.com/

  8. peter / 30.05.2016 в 10:19

    Recently, Cartier to join the World Women Economic and Social Forum, Yingshih (INSEAD) International Business School and McKinsey & Company co-founded “Cartier Xilinx surging female entrepreneur award” (Cartier Women’s Initiative Awards) officially opened its 2016 recruitment campaign, inviting entrepreneurial dreams and enterprising women entrepreneurs, log Cartier replica jewelry. submission before at 17:00 on August 31, 2016, turned entrepreneur dream Tour. This year’s winners will be the final women’s economic and social forum of global annual meeting in October 2016 held in France announced,Cartier Replica Jewelry.

  9. ourstjosephchurch.org / 09.07.2016 в 09:22

    August 31, 2016, turned entrepreneur dream Tour. This year’s winners will be the final women’s economic and social forum of global annual meeting in October 2016 held in France announced,Cartier Replica Jewelry.

  10. Миша / 09.05.2017 в 12:01

    Блог говно

Оставить комментарий

480×60
480×60