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);
- 它将使用第一个不等于属性进行比较。但上面的代码片段只是某些情况。我想确切地知道它是如何发生的以及为什么。因此,
问题
是:如何运作?我的意思是,更详细:
protected
/ private
属性视为总是计入此类比较? e.t.c。 - 如果有一些额外的条件/限制/规则会影响结果 - 请发帖。 Documentation仅表示==
/ ===
比较。此外,比较不同类的实例是不可能的,因为它将返回false
(显然)。
答案 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 的每一个提及与对象和密钥与属性交换在你的脑海中,你就拥有了确切描述这是如何工作的。我在上面的引用中省略了无用的数组细节。