Я прочитал несколько десятков обсуждений использования членов класса в качестве функций обратного вызова, но ни один из примеров не касается того, что кажется мне очевидным дизайном ООП, основанным на работе с другими языками ООП, такими как C ++ и Java.
Я определил метод сравнения внутри класса:
class TestClass { private $aField; // integer value function _construct($value) { $this->aField = $value; } // TestClass::_construct function compare($other) { if ($other instanceof TestClass) { // comparing two instances return $this->afield - $other->afield; } // comparing two events else throw new Exception("parameter is not instance of TestClass"); } // TestClass::compare } // class TestClass $instances = array(new TestClass(5),new TestClass(3)); // the following fails because: // 1. $this is not defined outside a class member // 2. compare does not take two parameters usort($instances, array($this, 'compare')); // the following kluge works around this function order($this, $that) { return $this->compare($that); } usort($instances, 'order');
Все примеры, которые я могу найти на этом форуме и в документации PHP, не являются полными, поскольку они не показывают контекст вызова usort. Теперь я могу обойти это, сделав функцию сравнения статической функцией с двумя параметрами и вызывая ее как вызываемый массивом («TestClass», «сравнить»), но неинтересно определять метод сравнения как статическую функцию класс. Основываясь на более чем 30-летнем опыте использования статических функций ООП, в большинстве случаев это результат плохого дизайна. В частности, статические методы преодолевают полиморфизм.
Я ищу функцию сортировки, подобную функции Java, которая использует интерфейс Comparable. Я вижу, что в 2010 году было обсуждено определение интерфейса Comparable, но это обсуждение связано только с операторами сравнения и делает неудобство PHP-пуристам, поскольку оно перегружает операторов. Однако интерфейс Java Comparable не перегружает операторы, поскольку с явным исключением класса String Java не поддерживает перегрузку операторов. Реализация интерфейса Comparable в Java позволяет использовать класс в SortedMaps и сортировать экземпляры в коллекции, но если вы хотите сравнить два объекта, вы должны явно вызвать метод compareTo. Я также вижу, что существует практически недокументированный метод compare_objects, который уже переопределяет стандартную реализацию операторов сравнения. Другими словами, несмотря на возражения пуристов, PHP уже позволяет вам перегружать операторов сравнения для класса. Однако недокументировано, использует ли функция сортировки PHP функции compare_objects при запросе сортировки объектов.
Вы вызываете $ за пределами своего класса.
$obj = new TestClass(); $sorted = usort($instances, array($obj, 'compare'));
Вы также можете сделать что-то вроде этого (не тестировали код)
class TestClass() { function compareWith($other) { $arr = array($this, $other); usort($arr, function($that, $other) { if ($other instanceof TestClass) { // comparing two instances return $other->afield - $that->afield; } // comparing two events else throw new Exception("parameter is not instance of TestClass"); }); return $arr; } } $instance1 = new TestClass(); $instance2 = new TestClass(); $sorted = $instance1->compareWith($instance2);
Вы упомянули класс коллекции в своих комментариях – вот пример использования (очень рудиментарный), в сочетании с методом сортировки, взятым из комментария пользователя в руководстве, которое я упомянул:
class Collection { private $itemType; private $items; public function __construct($itemType) { $this->itemType = $itemType; $this->items = []; } public function add($item) { if($item instanceof $this->itemType) { $this->items[] = $item; } else { throw new Exception('Only items of Type ' . $this->itemType . ' can be added!'); } } public function sort() { usort($this->items, array($this, 'compareItems')); var_dump($this->items); // test output, to check the result } private function compareItems($a, $b) { // calls the compare method of the item class return $a->compare($b); } } class TestClass { private $aField; public function __construct($value) { $this->aField = $value; } public function compare($other) { if($other instanceof TestClass) { return $this->aField - $other->aField; } else { throw new Exception('Parameter is not instance of TestClass!'); } } } $collection = new Collection('TestClass'); $collection->add(new TestClass(5)); $collection->add(new TestClass(1)); $collection->add(new TestClass(3)); $collection->sort();