Перегружать поведение count() при вызове определенных объектов

Возможный дубликат:
Считать элементы для объектов, реализующих ArrayAccess, используя count()?

В PHP 5 вы можете использовать магические методы, перегружать некоторые классы и т.д. В С++ вы можете реализовать функции, которые существуют до тех пор, пока разные типы аргументов. Есть ли способ сделать это в PHP?

Пример того, что я хотел бы сделать, это следующее:

class a {
    function a() {
        $this->list = array("1", "2");
    }
}

$blah = new a();

count($blah);

Я хотел бы, чтобы blah возвращался 2. IE подсчитывал значения определенного массива в классе. Итак, в С++ способ, которым я бы это сделал, может выглядеть так:

int count(a varName) { return count(varName->list); }

В принципе, я пытаюсь упростить вызовы данных для большого приложения, поэтому я могу это сделать:

count($object);

а не

count($object->list);

Список будет потенциально списком объектов, поэтому в зависимости от того, как он использовался, это может быть очень неприятное утверждение, если кто-то должен сделать это по-настоящему:

count($object->list[0]->list[0]->list);

Итак, могу ли я сделать что-то похожее на это:

function count(a $object) {
    count($object->list);
}

Я знаю, что PHP count принимает смешанный var, поэтому я не знаю, могу ли я переопределить отдельный тип.

Ответы

Ответ 1

Похоже, вы хотите реализовать интерфейс Countable:

class a implements Countable {
    public function __construct() {
        $this->list = array("1", "2");
    }

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

$blah = new a();

echo count($blah); // 2

Ответ 2

tl; dr - ответ внизу:)

В PHP эта модель обращена вспять; а не перегружать функции (а не методы) с разными типами аргументов, каждый класс предназначен для определения магических методов для каждой из этих функций.

Ниже приведен список функций, которые магическое поведение могут быть определены для вашего класса. В примерах каждая ссылка на $obj является экземпляром вашего класса, ->unknown относится к отсутствующему свойству, а ->blamethod() относится к отсутствующему методу.

  • __toString() - этот метод вызывается, когда ваш объект используется в контексте строки, например. echo "My object is: $obj\n";

  • __invoke([$arg1..n]) - когда ваш объект используется как функция, этот метод вызывается, например. $obj($a, $b);

  • __get($prop) - позволяет перехватить попытку доступа к несуществующему свойству вашего класса, например. $obj->unknown; Кстати, это иногда можно использовать как способ ленивой загрузки определенных свойств, которые в противном случае занимали бы значительную часть обработки, когда выполнялись в конструкторе.

  • __set($prop, $value) - вызывается при установке несуществующего свойства, например. $obj->unknown = 42;

  • __isset($prop) - вызвано, чтобы определить существование несуществующего свойства (я понимаю, как смешно звучит), например. isset($obj->unknown) вызовет $obj->__isset('unknown')

  • __unset($prop) - вызывается в таких случаях, как эти unset($obj->unknown);

  • __call($name, $arguments) - перехватывает вызов нереализованного метода вашего класса, например. $obj->blamethod(1, 2, 3); будет вызывать $obj->__call('blamethod', array(1, 2, 3));

  • __callStatic($name, $arguments) - как __call(), но вы не сможете использовать $this внутри своей реализации.

  • __ clone() - вызывается, когда вызывается $x = clone $obj;, поэтому вы решаете, какие данные хранятся и что выброшено.

С SPL было введено еще несколько концепций путем реализации определенных интерфейсов:

  • Traversable - абстрактный интерфейс, который определяет, что делает ваш класс при использовании в конструкции foreach; конкретный интерфейс называется Iterator.

  • ArrayAccess - интерфейс, который позволяет использовать экземпляры вашего класса для использования как массив.

  • Serializable - интерфейс, который определяет два метода для вызова serialize() или unserialize(). Он взаимно исключает использование __sleep() и __wakeup().

  • Countable - определяет один метод, который будет вызываться всякий раз, когда count() выполняется в вашем экземпляре класса.