【问题标题】:PHP: How do I check if all public methods of two classes return the same values?PHP:如何检查两个类的所有公共方法是否返回相同的值?
【发布时间】:2008-09-11 02:42:09
【问题描述】:

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

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

【问题讨论】:

    标签: php oop


    【解决方案1】:

    你也可以像这样实现一个 equal($other) 函数

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

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

    (未经测试)

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

    【讨论】:

      【解决方案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;
          }
      
      }
      

      【讨论】:

        【解决方案3】:

        您可以在类中定义 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,

        拉什

        【讨论】:

        • 尴尬,因为我实际上必须向我的类添加方法,但也许。 $a == $b 在比较之前是否隐式转换为字符串,因为这是我想用一个模拟框架做的事情,所以我没有选择在它上面运行一个字符串转换。
        【解决方案4】:

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

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

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

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

        【讨论】:

        • 我明白了,感谢您的帮助,不幸的是,我刚刚尝试了这个,为了使相等性为真,私有变量也必须包含相同的值。
        【解决方案5】:

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

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

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

        【讨论】:

          猜你喜欢
          • 2023-03-22
          • 2021-10-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-01-25
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多