2

实际上,如果我有一个class cand 的实例,$c1并且$c2 它可能具有不同的私有变量数量,但它们的所有公共方法都返回相同的值,我希望能够检查$c1 == $c2?

有谁知道一个简单的方法来做到这一点?

4

5 回答 5

2

很难准确地遵循你所追求的。您的问题似乎暗示这些公共方法不需要参数,或者如果它们需要,它们将是相同的参数。

使用内置的反射类可能会走得很远。

下面粘贴的是一个快速测试,我进行了比较两个类的所有公共方法的返回并确保它们相同。您可以轻松地对其进行修改以忽略不匹配的公共方法(即仅检查 class2 中存在于 class1 中的公共方法是否相等)。提供一组参数来传递会比较棘手 - 但可以通过一组方法名称/参数来调用每个类来完成。

无论如何,这可能包含一些对您有用的内容。

$class1 = new Class1();
$class2 = new Class2();
$class3 = new Class3();
$class4 = new Class4();
$class5 = new Class5();

echo ClassChecker::samePublicMethods($class1,$class2); //should be true
echo ClassChecker::samePublicMethods($class1,$class3); //should be false - different values
echo ClassChecker::samePublicMethods($class1,$class4); //should be false -- class3 contains extra public methods
echo ClassChecker::samePublicMethods($class1,$class5); //should be true -- class5 contains extra private methods

class ClassChecker {

    public static function samePublicMethods($class1, $class2) {

        $class1methods = array();

        $r = new ReflectionClass($class1);
        $methods = $r->getMethods();

        foreach($methods as $m) {
            if ($m->isPublic()) {
                @$result = call_user_method($m->getName(), $class1);
                $class1methods[$m->getName()] = $result;
            }
        }

        $r = new ReflectionClass($class2);
        $methods = $r->getMethods();

        foreach($methods as $m) {

            //only comparing public methods
            if ($m->isPublic()) {

                //public method doesn't match method in class1 so return false
                if(!isset($class1methods[$m->getName()])) {
                    return false;
                }

                //public method of same name doesn't return same value so return false
                @$result = call_user_method($m->getName(), $class2);
                if ($class1methods[$m->getName()] !== $result) {
                    return false;
                }
            }
        }

        return true;
    }
}


class Class1 {

    private $b = 'bbb';

    public function one() {
        return 999;
    }

    public function two() {
        return "bendy";
    }


}

class Class2 {

    private $a = 'aaa';

    public function one() {
        return 999;
    }

    public function two() {
        return "bendy";
    }
}

class Class3 {

    private $c = 'ccc';

    public function one() {
        return 222;
    }

    public function two() {
        return "bendy";
    }


}

class Class4 {

    public function one() {
        return 999;
    }

    public function two() {
        return "bendy";
    }

    public function three() {
        return true;
    }

}

class Class5 {

    public function one() {
        return 999;
    }

    public function two() {
        return "bendy";
    }

    private function three() {
        return true;
    }

}
于 2008-09-11T08:19:23.483 回答
2

您还可以实现一个 equal($other) 函数,例如

<?php
类Foo {
    公共函数等于($o){
        return ($o instanceof 'Foo') && $o.firstName()==$this.firstName();
    }
}

或使用 foreach 迭代一个对象的公共属性(此行为可能会被覆盖)并将它们与另一个对象的属性进行比较。

<?php
函数 equalsInSomeWay($a, $b) {
    if ( !($b instanceof $a) ) {
        返回假;
    }

    foreach($a as $name=>$value) {
        if ( !isset($b->$name) || $b->$name!=$value ) {
            返回假;
        }
    }
    返回真;
}

(未经测试)

或(或多或少)使用反射类相同,请参阅http://php.net/manual/en/language.oop5.reflection.php#language.oop5.reflection.reflectionobject
使用反射,您还可以实现更多鸭子-类型的比较,如果你愿意,比如“我不在乎它是一个实例还是同一个类,只要它具有相同的公共方法并且它们返回'相同'的值”
它真的取决于如何你定义“平等”。

于 2008-09-11T08:43:07.090 回答
1

您可以在类中定义 PHP 的__toString魔术方法。

例如

class cat {
    private $name;
    public function __contruct($catname) {
        $this->name = $catname;
    }

    public function __toString() {
        return "My name is " . $this->name . "\n";
    }
}

$max = new cat('max');
$toby = new cat('toby');
print $max; // echoes 'My name is max'
print $toby; // echoes 'My name is toby'

if($max == $toby) {
    echo 'Woohoo!\n';
} else {
    echo 'Doh!\n';
}

然后您可以使用相等运算符来检查两个实例是否相等。

高温下,

鲁士

于 2008-09-11T03:02:59.983 回答
1

乔治:你可能已经看过了,但它可能会有所帮助:http ://usphp.com/manual/en/language.oop5.object-comparison.php

使用比较运算符(==)时,对象变量的比较方式很简单,即:如果两个对象实例具有相同的属性和值,并且是同一类的实例,则它们相等。

它们不会被隐式转换为字符串。

如果你想做比较,你最终会修改你的类。您还可以使用 getter 和 setter 编写一些自己的 todo 比较方法

于 2008-09-11T03:18:06.640 回答
0

您可以尝试编写自己的类到插件并编写根据您定义的内容进行比较的方法。例如:

class Validate {
    public function validateName($c1, $c2) {
        if($c1->FirstName == "foo" && $c2->LastName == "foo") {
            return true;
        } else if (// someother condition) {
            return // someval;
        } else {
            return false;
        }
    }

    public function validatePhoneNumber($c1, $c2) {
        // some code
    }
}

这可能是您不必修改预先存在的类代码的唯一方法

于 2008-09-11T04:34:40.107 回答