问题
Possible Duplicate:
Count elements for objects implementing ArrayAccess using count()?
In PHP 5, you can use magic methods, overload some classes, etc. In C++, you can implement functions that exist as long as the argument types are different. Is there a way to do this in PHP?
An example of what I'd like to do is this:
class a {
function a() {
$this->list = array("1", "2");
}
}
$blah = new a();
count($blah);
I would like blah to return 2. IE count the values of a specific array in the class. So in C++, the way I would do this might look like this:
int count(a varName) { return count(varName->list); }
Basically, I am trying to simplify data calls for a large application so I can call do this:
count($object);
rather than
count($object->list);
The list is going to be potentially a list of objects so depending on how it's used, it could be really nasty statement if someone has to do it the current way:
count($object->list[0]->list[0]->list);
So, can I make something similar to this:
function count(a $object) {
count($object->list);
}
I know PHP's count accepts a mixed var, so I don't know if I can override an individual type.
回答1:
It sounds like you want to implement the Countable interface:
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 - answer is at the bottom :)
In PHP, this model is reversed; rather than overloading functions (not methods) with different argument types, each class is meant to define magic methods for each of those functions.
Below is the list of functions that magic behaviour can be defined for inside your class. In the examples, each reference to $obj
is an instance of your class, ->unknown
refers to a missing property and ->blamethod()
refers to a missing method.
__toString() - this method is called when your object is used in a string context, e.g.
echo "My object is: $obj\n";
__invoke([$arg1..n]) - when your object is used as a function, this method gets called, e.g.
$obj($a, $b);
__get($prop) - allows for intercepting an attempt to access a non-existing property of your class, e.g.
$obj->unknown
; btw, this can sometimes be used as a way to lazy load certain properties that would otherwise take a considerable amount of processing when done in the constructor.__set($prop, $value) - gets called when a non-existing property is being set, e.g.
$obj->unknown = 42;
__isset($prop) - called to determine the existence of a non-existing property (I realize how funny that sounds), e.g.
isset($obj->unknown)
would call$obj->__isset('unknown')
__unset($prop) - called in cases like these
unset($obj->unknown);
__call($name, $arguments) - intercepts a call to an unimplemented method of your class, e.g.
$obj->blamethod(1, 2, 3);
will invoke$obj->__call('blamethod', array(1, 2, 3));
__callStatic($name, $arguments) - like
__call()
but you will not be able to use$this
inside your implementation.__clone() - called when
$x = clone $obj;
is called, so you get to decide what data is kept and what's thrown away.
With SPL, a few more concepts were introduced by means of implementing certain interfaces:
Traversable - an abstract interface that defines what your class does when used in a
foreach
construct; the concrete interface is called Iterator.ArrayAccess - an interface that allows using instances of your class to be used like an array.
Serializable - an interface that defines two methods to be called upon
serialize()
orunserialize()
. It's mutually exclusive to using__sleep()
and__wakeup()
.Countable - defines one method to be called whenever
count()
is performed on your class instance.
来源:https://stackoverflow.com/questions/8510061/overload-the-behavior-of-count-when-called-on-certain-objects