无法为usort

时间:2015-06-26 22:31:21

标签: php oop

我已经阅读了几十个关于使用类成员作为回调函数的讨论,但是基于与其他OOP语言(如C ++和Java)的协作,没有一个示例解决了我认为明显的OOP设计。

我在课堂上定义了一个比较方法:

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','比较')但是它不直观将比较方法定义为类的静态函数。基于在OOP中超过30年的个人经验,静态功能在大多数情况下是由于糟糕的课堂设计造成的。特别是静态方法会破坏多态性。

我正在寻找的是类似于Java的排序函数,它利用了Comparable接口。我看到有一些关于定义Comparable接口的讨论可以追溯到2010年,但是这个讨论只与比较运算符有关,并且让PHP纯粹主义者感到不舒服,因为它会使运算符超载。但是,Java Comparable接口执行重载运算符,因为由于String类的明显异常,Java不支持重载运算符。在Java中实现Comparable接口使您可以使用SortedMaps中的类并对Collection中的实例进行排序,但是如果要比较两个对象,则必须显式调用compareTo方法。我还看到有一个基本上没有文档的compare_objects方法,它已经覆盖了比较运算符的默认实现。换句话说,尽管纯粹主义者'反对意见PHP已经允许你重载一个类的比较运算符。但是,当要求排序对象时,PHP排序函数是否使用compare_objects是无法记录的。

2 个答案:

答案 0 :(得分:2)

你在课堂外打电话给$ this。

$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);

答案 1 :(得分:1)

你在评论中提到了一个集合类 - 所以这里是一个使用(一个非常基础的)的例子,结合我提到的手册中用户评论的排序方法:

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();