PHP中的对象比较

时间:2014-03-20 09:24:30

标签: php object comparison

SO,

问题

它并不为人所知,但PHP允许比较对象 - 而不仅仅是平等== - 而是<>。但是 - 它是如何工作的?因此,如果我想创建类似的对象 - 他们应该遵循哪些限制/规则?

最有用的案例是DateTime()个对象 - 它们具有一定的时间戳,可以进行比较(这具有逻辑意义)。在lxr上有DateTime的一些解释。但是常见的情况呢?

我有:

class C
{
   protected $holder;
   protected $mirror;
   public function __construct($h = null)
   {
      $this->holder=$h;
      $this->mirror=-1*$h;
   }
}


$one = new C(1);
$two = new C(2);
//false, false, true: used $holder
var_dump($one>$two, $one==$two, $one<$two);

- 如果我要更改属性声明顺序,它将使用$mirror

class C
{
   //only order changed:
   protected $mirror;
   protected $holder;
   public function __construct($h = null)
   {
      $this->holder=$h;
      $this->mirror=-1*$h;
   }
}

$one = new C(1);
$two = new C(2);
//true, false, false: used $mirror
var_dump($one>$two, $one==$two, $one<$two);

所以似乎'规则'之一是它将使用第一个声明的属性。但是为什么使用protected属性根本不清楚。

现在,更复杂的样本:

class Test
{
  protected $a;
  protected $b;

  function __construct($a, $b)
  {
    $this->a = $a;
    $this->b = $b;
  }
}

$x = new Test(1, 2);
$y = new Test(1, 3);

// true, false, false
var_dump($x < $y, $x == $y, $x > $y);

$x = new Test(3, 1);
$y = new Test(2, 1);

// false, false, true
var_dump($x < $y, $x == $y, $x > $y);

- 它将使用第一个不等于属性进行比较。但上面的代码片段只是某些情况。我想确切地知道它是如何发生的以及为什么。因此,

问题

是:如何运作?我的意思是,更详细:

  • 我可以依赖这样的事实:PHP会使用第一个不等于的属性进行比较吗?
  • 如果属性数量不相等,将会怎样做? (即某些属性在代码执行期间动态添加到实例中)
  • 我是否可以将protected / private属性视为总是计入此类比较?

e.t.c。 - 如果有一些额外的条件/限制/规则会影响结果 - 请发帖。 Documentation仅表示== / ===比较。此外,比较不同类的实例是不可能的,因为它将返回false(显然)。

3 个答案:

答案 0 :(得分:3)

PHP按顺序(按声明的顺序)比较对象属性,并在找到的第一个inequal属性处停止。这种行为没有记录,所以除了查看PHP的来源之外,遗憾的是,除此之外没有太多可说的。

没有记录通常是&#34;不依赖它的同义词&#34;。

答案 1 :(得分:2)

php中的每个类都有一个与处理函数相关的结构(在c代码中),它看起来像

struct _zend_object_handlers {
    /* general object functions */
    zend_object_add_ref_t                   add_ref;
    zend_object_del_ref_t                   del_ref;
[...]
    zend_object_compare_t                   compare_objects;
[...]
};

compare_objects指向一个&#34;带两个对象的函数&#34;并根据此比较器定义的顺序返回-1,0,1(就像strcmp()对字符串所做的那样) 只有当两个操作数(对象)指向相同的比较函数时才使用此函数 - 但是让我们坚持这种情况。
这就是例如DateTime&#34;添加&#34;它比较两个DateTime实例的功能,它只定义另一个特定于DateTime的compare_objects函数,并将其放在描述其类的结构中。

static void date_register_classes(TSRMLS_D)
{
[...]

    INIT_CLASS_ENTRY(ce_date, "DateTime", date_funcs_date);
    ce_date.create_object = date_object_new_date;
[...]
    date_object_handlers_date.compare_objects = date_object_compare_date;

因此,如果您想(确切地)知道两个DateTime实例的比较方式,请查看date_object_compare_date

comparision described in the manual(至少对于cmp(o1,o2)== 0)似乎是在zend_std_compare_objects中实现的。它被StdClass和一个简单的用户定义类使用,例如像。

<?php
class Foo { }
$a = new StdClass;
$b = new Foo;

$a > $b;

但是其他类(在php扩展中)确实设置了其他功能。 DateTime,ArrayObject,PDOStatement,甚至Closures使用不同的功能 但我还没有找到一种在脚本代码中定义比较函数/方法的方法(但看起来太难/太长)

答案 2 :(得分:0)

确切的行为在PHP language specification中定义,因此,您可以依赖它。

  

[...]如果对象的类型不同,则比较结果为FALSE。如果对象属于同一类型,则使用上述数组比较对象的属性进行比较 [sic]

数组比较定义如下:

  

[...]对于具有相同数量元素的数组,左操作数中的键被逐一考虑,如果左侧操作数中的下一个键存在于右侧操作数中,则会比较相应的值。如果它们不相等,则包含较小值的数组被认为小于另一个数组,并且比较结束;否则,使用下一个元素重复该过程。 [...]如果所有值都相等,则认为数组相等。

只需将 array 的每一个提及与对象密钥属性交换在你的脑海中,你就拥有了确切描述这是如何工作的。我在上面的引用中省略了无用的数组细节。