PHP:如何检查两个类的所有公共方法是否返回相同的值?

时间:2020-03-05 18:51:12  来源:igfitidea点击:

实际上,如果我有class c以及$ c1$ c2的实例
可能具有不同的私有变量数量,但所有公共方法都返回相同的值,我希望能够检查" $ c1 == $ c2?"

有人知道这样做的简单方法吗?

解决方案

回答

我们可以在类中定义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';
}

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

HTH,

鲁西

回答

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

When using the comparison operator (==), object variables are compared in a simple manner, namely: Two object instances are equal if they have the same attributes and values, and are instances of the same class.

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

如果要进行比较,最终将修改类。我们还可以使用getter和setter编写自己的待办事项比较方法

回答

我们可以尝试编写自己的类来插入插件,并编写根据定义进行比较的方法。例如:

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
    }
}

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

回答

很难完全按照要求进行操作。问题似乎暗示着这些公共方法不需要参数,或者如果使用它们,它们将是相同的参数。

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

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

无论如何,其中可能包含一些可能对我们有用的位。

$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;
    }

}

回答

我们还可以实现equal($ other)函数,例如

<?php
class Foo {
    public function equals($o) {
        return ($o instanceof 'Foo') && $o.firstName()==$this.firstName();
    }
}

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

<?php
function equalsInSomeWay($a, $b) {
    if ( !($b instanceof $a) ) {
        return false;
    }

    foreach($a as $name=>$value) {
        if ( !isset($b->$name) || $b->$name!=$value ) {
            return false;
        }
    }
    return true;
}

(未试)

或者(或者多或者少)使用反射类的对象,请参见http://php.net/manual/zh-CN/language.oop5.reflection.php#language.oop5.reflection.reflectionobject
如果需要,通过反射,我们还可以实现更鸭式的比较,例如"只要它具有相同的公共方法并且它们返回'相同的价值"
这实际上取决于我们如何定义"等于"。