Intereting Posts

Есть ли метод __equals в PHP, как в Java?

Есть ли шаблон или магический метод, который вы можете использовать в PHP, чтобы определить, когда сравнивать два экземпляра класса?

Например, в Java я мог бы легко переопределить метод equals и создать собственный способ проверки и сравнения двух экземпляров.

В мире? Нет. Нет метода __equals magic. В руководстве есть полный список магических методов.

Ты можешь сделать

 $myObject1 == $myObject2 

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

Я часто сам хотел использовать этот тип метода, но я думаю, что более полезным будет метод __compare() который будет вызываться для любого оператора сравнения <,>, ==, === и т. Д., Который уже существует для Встроенные классы PHP, как видно из вики – страницы PHP, и есть пример того, как это можно реализовать в книге PHPInternals :

compare_objects

 int (*compare)(zval *object1, zval *object2 TSRMLS_DC) 

Сравнивает два объекта. Используется для операторов ==,! =, <,>, ⇐ и> =. Реализации должны следовать этим правилам – для любых объектов a, b и c, которые используют один и тот же обработчик сравнения:

Один из способов, который я использовал для этого, – реализовать интерфейс Comparable, например:

 interface Comparable { /** * @param Comparable $other * @param String $comparison any of ==, <, >, =<, >=, etc * @return Bool true | false depending on result of comparison */ public function compareTo(Comparable $other, $comparison); } 

Детали сравнения объектов и все остальное ООП можно найти здесь http://www.php.net/manual/en/language.oop5.php .

Это может быть реализовано на PHP 7 .

К сожалению нет, но вы можете легко воспроизвести что-то близкое. Например:-

 <?php interface IComparable { public function compare(self $subject); } class Foo implements IComparable { public function compare(self $subject) { return $this->__toString() === $subject->__toString(); } public function __toString() { return serialize($this); } } function compare(IComparable $a, IComparable $b) { return $a->compare($b); } $a = new Foo; $b = new Foo; var_dump(compare($a, $b)); //true $a->name = 'A'; $b->name = 'B'; var_dump(compare($a, $b)); //false 

Это не особенно элегантно, но должно быть вам на пути.

Энтони.

Прежде всего, оператор == достаточно в большинстве случаев, особенно если речь идет о объектах значений. Просто не забудьте предоставить __toString если вы хотите сравнить экземпляр со скалярными значениями.

 <?php final class ValueObject { private $value; public function __construct($value) { $this->value = $value; } public function __toString() { return (string) $this->value; } } $a = new ValueObject(0); $b = new ValueObject(1); var_dump( $a == $b, // bool(false) $a == $a, // bool(true) $b == $b, // bool(true) $a == '0', // bool(true) $b == '1' // bool(true) ); 

Есть одна проблема с этим, вы не можете сравнивать со скалярным типом, отличным от строки (по крайней мере, не в PHP 5 и 7), потому что он будет жаловаться, что экземпляр не может быть преобразован в желаемое значение. Следовательно, вам всегда нужно убедиться, что тип значения, с которым вы сравниваете, является строкой.

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

 <?php interface Comparable { function compareTo(Comparable $other): int; } function class_compare(Comparable $a, Comparable $b): int { return $a->compareTo($b); } final class C implements Comparable { private $value; public function __construct(int $value) { $this->value = $value; } public function compareTo(Comparable $other): int { assert($this instanceof $other && $other instanceof $this); return $this->value <=> $other->value; } } $c1 = new C(0); $c2 = new C(0); var_dump($c1->compareTo($c2)); // int(0) $c0 = new C(0); $c1 = new C(1); $c2 = new C(2); $actual = [$c2, $c1, $c0]; usort($actual, 'class_compare'); var_dump($actual === [$c0, $c1, $c2]); // bool(true) 

Утверждение важно, так как у нас нет никаких генериков в PHP. Это довольно печальное состояние вещей, и нет никакого претворенного способа реализовать это.

Я стараюсь сделать следующее.

 <?php final class SomeClass { private $value; public function __construct($value) { $this->value = $value; } public static function compare(SomeClass $a, SomeClass $b): int { return $a->compareTo($b); } public function compareTo(SomeClass $other): int { return $this->value <=> $other->value; } public function isEqual($other): bool { return $other instanceof $this && $other->value === $this->value; } public function isIdentical($other): bool { return $other instanceof $this && $this instanceof $other && $other->value === $this->value; } } 

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

В принципе, как все говорят, это будет делать:

 $object1 == $object2 

Сравнивает тип и свойства.


Но то, что я делаю в этих случаях, когда я хочу персонализировать свои методы равенства, реализует магический метод __toString () в классах, в которых я хочу утверждать равенство.

 class Car { private $name; private $model; ... public function __toString() { return $this->name.", ".$this->model; } } 

И тогда, когда я хочу сделать сравнение, я просто делаю это:

 $car1->toString() === $car2->toString() 

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

Другой вариант (как состояния halfer в комментариях) реализует равный метод, который утверждает равенство другого экземпляра того же класса. Например:

 class Car { private $name; private $model; ... public function equals(Car $anotherCar) { if($anotherCar->getName() !== $this->name) { return false; } if($anotherCar->getModel() !== $this->model) { return false; } ... return true; } } 

Если вы хотите сравнить свой пользовательский объект, вы можете сделать это следующим образом:

 $time1 = new MyTimeClass("09:35:12"); $time2 = new MyTimeClass("09:36:09"); if($time1 > $time2) echo "Time1 is bigger"; else echo "Time2 is bigger"; //result: Time1 is bigger 

Он сравнивает первое свойство, найденное в классе, в моем случае значение int, которое содержит общее количество секунд в заданное время. Если вы поместите свойство $ seconds сверху, вы заметите, что это дает неожиданный «Time1 больше».

 class MyTimeClass { public $intValue; public $hours; public $minutes; public $seconds; public function __construct($str){ $array = explode(":",$str); $this->hours = $array[0]; $this->minutes = $array[1]; $this->seconds = $array[2]; $this->intValue = ($this->hours * 3600) + ($this->minutes * 60) + $this->seconds; } }