【问题标题】:Auto-check equality of two objects?自动检查两个对象的相等性?
【发布时间】:2016-04-18 03:25:40
【问题描述】:

我需要检查两个 PHP 对象的值是否相等。当然,我可以轻松地将isEqualTo(...) 方法添加到比较所有相关值的类中。然而,具体的课程将在不久的将来发生变化,我想知道是否有任何自动化的方法可以做到这一点。

例子:

class Contact {
    private name;       // String
    private phone;      // Int
    private someObject; // Custom Object

    public function getName() {
        return $this->name;
    }

    public function setName($newName) {
        $this->name = $newName;
    }


    public function getPhone() {
        return $this->phone;
    }

    public function setPhone($newPhone) {
        $this->phone = $newPhone;
    }


    public function getSomeObject() {
        return $this->someObject;
    }

    public function setSomeObject($newObj) {
        $this->someObject = $newObj;
    }


    // Manual Solution 
    public function isEqualTo($contact) {
         result  = $this->name == $contact->getName();
         result &= $this->phone == $contact->getPhone();

         result &= $this->someObject == $contact->getSomeObject();

         return result;
    }
} 

这显然可行。当然,我知道比较 someObject 的局限性(必须是确切的某个对象才能为真),但这没关系。

不过,Contact 类将在不久的将来扩展。每次我向类添加新属性/值时,我都必须将它们添加到isEqualTo。没什么大不了的,就是有点麻烦。

那么,有没有办法实现isEqualTo 自动所有可用的公共属性?

我找到了get_class_varsget_object_vars,但是这些方法不适用于getter 和setter,而只能用于可以直接访问的var。

我找到了get_class_methodes,但这会返回所有方法,而不仅仅是 getter 和 setter。通过get...set... 过滤方法名称当然可以,但这更像是一种黑客攻击,而不是“干净整洁”的解决方案。

简而言之:是否有任何“正确”的方法来自动检查两个 PHP 对象是否相等?

【问题讨论】:

    标签: php class object equality


    【解决方案1】:

    我不会说这是“正确”的方式,但由于您不想实现/维护自己的比较函数/方法,您可能对 php 的默认行为(包括比较)感兴趣受保护/私有财产:

    <?php
    class Foo {
        private $x,$y,$z;
        public function __construct($x,$y,$z) {
            $this->x = $x;
            $this->y = $y;
            $this->z = $z;
        }
    }
    
    $f1 = new Foo(1,2,3);
    $f2 = new Foo(4,5,6);
    $f3 = new Foo(1,2,3);
    
    var_dump(
        $f1==$f2,
        $f1==$f3
    );
    

    打印

    bool(false)
    bool(true)
    

    这对你来说可能够也可能不够。


    作为pointed out by Alma Do,循环引用例如

    <?php
    class Foo {
        private $x,$y,$z;
        public function __construct($x,$y,$z) {
            $this->x = $x;
            $this->y = $y;
            $this->z = $z;
        }
    
        public function setZ($z) {
            $this->z = $z;
        }
    }
    
    
    $f1 = new Foo(1,2,3);
    $f2 = new Foo(4,5,6);
    $f3 = new Foo(1,2,3);
    
    $f1->setZ($f3);
    $f3->setZ($f1);
    
    
    var_dump(
        $f1==$f2,
        $f1==$f3
    );
    

    将导致Fatal error: Nesting level too deep - recursive dependency?

    【讨论】:

    • 这将在循环引用上失败(以一种糟糕的方式,导致致命错误)。使用时要记住这一点。
    • 确实如此。将其添加到答案中(还有其他问题,但这可能是最明显和最引人注目的)。
    • 嗯,“循环引用” - 我的意思不仅仅是狭义的对象案例。可能没有跨对象引用,而是甚至是跨属性(或内联属性)递归。没有嵌套对象的示例案例是数组,例如this snippet。因此,您的示例是有效的,我只是注意到遍历比较的递归结构在 PHP 中效果不佳。缓解这种情况的常用方法是使用 DFS 和自定义用户函数(通过反射对象)
    【解决方案2】:

    您可以使用反射来执行此操作,但我认为这不是一个好主意。也许 serialize() 是一个更好的解决方案?

    function isEquals(self $obj){
    return serialize($obj)===serialize($this)
    }
    

    【讨论】:

      猜你喜欢
      • 2015-07-19
      • 2019-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-25
      • 1970-01-01
      • 2016-06-27
      相关资源
      最近更新 更多