PHP中的对象比较



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);

-因此它将使用first not equal属性进行比较。但上面的代码片段只是一些情况。我想知道它到底是怎么发生的,为什么。因此,

问题

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

  • 我可以相信PHP会使用第一个不相等的属性进行比较吗
  • 如果属性数不相等,该怎么办?(即在代码执行期间,某些属性被动态添加到实例中(
  • 我是否可以将protected/private属性视为始终被计算用于此类比较

e.t.c.-所以如果有一些额外的条件/限制/规则会影响结果-请张贴。文档状态仅用于==/===比较。此外,比较不同类的实例是不可能的,因为它将返回false(显然(。

PHP按顺序(按声明顺序(比较对象属性,并在找到的第一个不等属性处停止。这种行为没有被记录下来,所以除了查看PHP的来源之外,没有什么好说的。

未记录通常是"不要依赖它"的同义词。

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指向一个"接受两个对象"的函数,并根据该比较器定义的顺序返回-1.0,1(就像strcmp((对字符串所做的那样(
只有当两个操作数(对象(都指向同一个比较函数时,才使用此函数,但让我们继续使用这种情况
这就是DateTime"添加"其功能以比较两个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

手册中描述的比较(至少在cmp(o1,o2(==0的情况下(似乎在zend_std_compare_objects中实现。StdClass和一个简单的用户定义类(如(都使用它

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

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

PHP语言规范中定义了确切的行为,因此,您可以依赖它。

[…]如果对象的类型不同,则比较结果为FALSE。如果对象的类型相同,则使用上述数组比较来比较对象的属性。

阵列比较定义如下:

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

只要将数组对象的每一次提及与property交换,您就可以准确地描述这是如何工作的。我在上面的引用中省略了无用的数组细节。

相关内容

  • 没有找到相关文章

最新更新