PHP:如何检查两个类的所有公共方法是否返回相同的值?
实际上,如果我有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
如果需要,通过反射,我们还可以实现更鸭式的比较,例如"只要它具有相同的公共方法并且它们返回'相同的价值"
这实际上取决于我们如何定义"等于"。