16

可能重复:
使用 count() 为实现 ArrayAccess 的对象计数元素?

在 PHP 5 中,您可以使用魔术方法、重载某些类等。在 C++ 中,您可以实现只要参数类型不同就存在的函数。有没有办法在 PHP 中做到这一点?

我想做的一个例子是:

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

$blah = new a();

count($blah);

我希望 blah 返回 2。IE 计算类中特定数组的值。所以在 C++ 中,我这样做的方式可能如下所示:

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 的计数接受混合 var,所以我不知道是否可以覆盖单个类型。

4

2 回答 2

34

听起来你想实现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
于 2011-12-14T18:54:42.873 回答
23

tl;博士 - 答案在底部:)

在 PHP 中,这个模型是相反的;不是重载具有不同参数类型的函数(不是方法),而是每个类都旨在为每个函数定义魔术方法。

下面是可以在您的类中定义魔术行为的函数列表。在示例中,每个对的引用$obj都是您的类的一个实例,->unknown指的是缺失的属性和->blamethod()缺失的方法。

  1. __toString()- 当您的对象在字符串上下文中使用时调用此方法,例如echo "My object is: $obj\n";

  2. __invoke([$arg1..n])- 当您的对象用作函数时,会调用此方法,例如$obj($a, $b);

  3. __get($prop)- 允许拦截访问类的不存在属性的尝试,例如$obj->unknown;顺便说一句,这有时可以用作延迟加载某些属性的方法,否则这些属性在构造函数中完成时会进行大量处理。

  4. __set($prop, $value)- 在设置不存在的属性时调用,例如$obj->unknown = 42;

  5. __isset($prop)- 调用以确定不存在的属性的存在(我意识到这听起来很有趣),例如isset($obj->unknown)会调用$obj->__isset('unknown')

  6. __unset($prop)- 在这样的情况下调用unset($obj->unknown);

  7. __call($name, $arguments)- 拦截对类的未实现方法的调用,例如$obj->blamethod(1, 2, 3);将调用$obj->__call('blamethod', array(1, 2, 3));

  8. __callStatic($name, $arguments)- 喜欢__call(),但您将无法$this在您的实现中使用。

  9. __clone() - 在被调用时$x = clone $obj;调用,因此您可以决定保留哪些数据以及丢弃哪些数据。

在 SPL 中,通过实现某些接口引入了更多概念:

  1. Traversable- 一个抽象接口,它定义了你的类在foreach构造中使用时的作用;调用具体接口Iterator

  2. ArrayAccess- 一个允许使用类的实例的接口,可以像数组一样使用。

  3. Serializable- 定义两个要调用的方法的接口serialize()unserialize()__sleep()使用和是互斥的__wakeup()

  4. Countablecount()- 定义一种在您的类实例上执行时要调用的方法。

于 2012-09-03T09:36:22.843 回答