PHP: Как проверить, все ли открытые методы двух классов возвращают одинаковые значения? - PullRequest
2 голосов
/ 11 сентября 2008

В действительности, если у меня есть class c и экземпляры $c1 и $c2 которые могут иметь разные частные значения переменных, но все их открытые методы возвращают одинаковые значения, я хотел бы проверить, что $c1 == $c2?

Кто-нибудь знает простой способ сделать это?

Ответы [ 5 ]

2 голосов
/ 11 сентября 2008

Вы также можете реализовать такую ​​же ($ 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;
}

(непроверенные)

или (более или менее) то же самое с использованием классов Reflection, см. http://php.net/manual/en/language.oop5.reflection.php#language.oop5.reflection.reflectionobject
С помощью отражения вы также можете реализовать более типизирующий тип сравнения, если хотите, например: «Мне все равно, является ли он экземпляром или тем же классом, если он имеет те же открытые методы и они возвращают одинаковые «значения»
это действительно зависит от того, как вы определяете «равно».

1 голос
/ 11 сентября 2008

Трудно точно следовать тому, что вы ищете. Ваш вопрос, кажется, подразумевает, что эти публичные методы не требуют аргументов, или что если бы они это сделали, они были бы такими же аргументами.

Вероятно, вы могли бы довольно далеко уйти, используя встроенные классы отражения.

Ниже приведен быстрый тест, который я провел, чтобы сравнить результаты всех открытых методов двух классов и убедиться, что они одинаковы. Вы можете легко изменить его, чтобы игнорировать несовпадающие публичные методы (то есть проверять равенство только открытых методов в 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;
    }

}
1 голос
/ 11 сентября 2008

Джордж: Возможно, вы уже видели это, но это может помочь: http://usphp.com/manual/en/language.oop5.object-comparison.php

При использовании оператора сравнения (==) переменные объекта сравниваются простым способом, а именно: два экземпляра объекта равны, если они имеют одинаковые атрибуты и значения и являются экземплярами одного и того же класса.

Они не преобразуются неявно в строки.

Если вы хотите сделать сравнение, вы в конечном итоге измените свои классы. Вы также можете написать собственный метод сравнения задач, используя getters & setters

1 голос
/ 11 сентября 2008

Вы можете определить магический метод 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';
}

Затем вы можете использовать оператор равенства, чтобы проверить, равны ли оба экземпляра.

НТН,

Rushi

0 голосов
/ 11 сентября 2008

Вы можете попробовать написать собственный класс для плагина и написать методы, которые делают сравнение на основе того, что вы определили. Например:

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

Вероятно, это будет единственный способ изменить существующий код класса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...