Перегружать поведение 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()
выполняется в вашем экземпляре класса.