3

由于必须第一次定义相关对象之间的关系,我发现自己花了整个周末在网上搜索有关equals()compareTo(). 在发现很少有用的信息后,我决定自己找到解决方案。我相信以下是该解决方案在compareTo()方法方面的体现。我有一个想法,类似的技术也可能适用于该equals()方法。

我希望比我更聪明的人有时间验证这些发现并就可能遇到的任何陷阱提供反馈。

// The name chosen for the following class shell ("Base") is intended to
// portray that this compareTo() method should be implemented on a base class
// as opposed to a subclass.
public class Base
implements Comparable<Base>
{
    /**
     * Compares this Base to the specified Object for semantic ordering.
     *
     * @param other The Object to be compared.
     *
     * @return An int value representing the semantic relationship between the
     *         compared objects. The value 0 is returned when the two objects
     *         are determined to be equal (as defined by the equals method).
     *         A positive value may be returned if the "other" object is a
     *         Base and the "exact types" comparison determines this Base to
     *         have a higher semantic ordering than the "other" object, if the
     *         "other" object is not a Base, or if the "other" object is a
     *         subclass of Base who's compareTo method determines itself to
     *         have a lower semantic ordering than this Base. A negative value
     *         may be returned if the "other" object is a Base and the
     *         "exact types" comparison determines this Base to have a lower
     *         semantic ordering than the "other" object or if the "other"
     *         object is a subclass of Base who's compareTo method determines
     *         itself to have a higher semantic ordering than this Base.
     */
    public int compareTo(Base other)
    {
        int relationship = 0;

        if (other == null)
            throw new NullPointerException("other: Cannot be null.");

        if (!this.equals(other))
        {
            if (this.getClass() == Base.class)
            {
                if (this.getClass == other.getClass())
                    relationship = // Perform comparison of exact types;
                else
                    relationship = -1 * other.compareTo(this);
            }
            else
                relationship = 1;
        }

        return relationship;
    }
4

2 回答 2

3

这行不通。考虑两个类,A它们B直接扩展Base并且其实例从不相等。然后是两个实例Base a = new A();Base b = new B()。既然this.getClass() == Base.classwill be falsefor both aand b,那么情况就是 thata.compareTo(b) == 1和 that b.compareTo(a) == 1。这违反了所有人的通用合同并且Comparable具有可比性。sgn(x.compareTo(y)) == -sgn(y.compareTo(x))xy

对于比较对象所涉及的一些微妙之处,特别是测试子类之间的相等性,我推荐这篇优秀的文章

于 2012-07-30T07:18:56.980 回答
0

正如主题启动器中所述,我开始这个项目是因为缺乏详细说明构建干净可覆盖compareTo()方法背后的过程的可用信息。我希望您会发现以下是这样的实现。Ted Hopp 给我补充了一些我最初忽略的关键元素。

您会发现 RelationalObject 的实现没有定义任何元素之间的初始关系,除了那些不是来自同一层次分支的元素,它认为这是无法比较的(当然,是可覆盖的)。由于此类可能实现的任何关系都无法考虑其派生类的那些状态元素,因此我确定最好将此任务完全留给用户。

这个类的目的是使更改新子类型(包括当前未实现的子类型)的关系行为变得更容易。

因为我在主题启动器中表达了对文档的渴望,所以我对每种方法进行了大量评论,希望它可以提供一些指导。

我希望有足够时间的人愿意提供这些结果的验证。虽然我已尽力考虑所有可能的情况,但获得反馈总是很好的。(正面或负面)

public abstract class RelationalObject
implements Comparable<RelationalObject>
{
    /*
     * Compares two RelationalObjects for semantic ordering.
     *
     * @param other The RelationalObject to be compared.
     *
     * @return An int value representing the semantic relationship between the
     *         two RelationalObjects. A value of 0 is returned if the two
     *         objects are determined to be equal. A negative value is
     *         returned if "this" object is determined to have a
     *         lower semantic ordering than the "other" object. A positive
     *         value is returned if "this" object is determined to have a
     *         highter semantic ordering than the "other" object.
     */
    public final int compareTo(RelationalObject other)
    throws ClassCastException, NullPointerException
    {
        if (other == null)
            throw new NullPointerException("other: Cannot be null.");

        int relation = 0;

        if (!this.equals(other))
        {
            if (this.getClass().isAssignableFrom(other.getClass()))
            {
                if (this.getClass() == other.getClass())
                    relation = this.compareToExactType(other);
                else
                    relation = -1 * other.compareTo(this);
            }
            else
            {
                if (other.getClass().isInstance(this))
                    relation = this.compareToSuperType(other);
                else
                    relation = other.compareToForeignType(this);
            }
        }

        return relation;
    }

    /*
     * Compares two RelationalObjects with the exact same class type for
     * semantic ordering. The comparison may be based upon any of the class
     * state elements so long as the compareTo() method contract is not
     * broken.
     *
     * @param exact The RelationalObject with exactly matching type to be
     *              compared.
     *
     * @return An int value representing the semantic relationship between the
     *         two RelationalObjects.
     */
    protected abstract int compareToExactType(RelationalObject exact);

    /*
     * Compares two RelationalObjects not within the same hierarchical branch
     * for semantic ordering. The comparison may be based upon only those
     * state elements common to both objects (i.e. A comparison must be made
     * between each element and the pair's common ancestor). Should the two
     * results be equal, a ClassCastException must be thrown as the objects do
     * not contain enough distinct information to be further compared.
     *
     * @param foreign The RelationalObject from a foreign hierarchical branch
     *                to be compared.
     *
     * @return An int value representing the semantic relationship between the
     *         two RelationalObjects.
     */
    protected abstract int compareToForeignType(RelationalObject foreign);

    /*
     * Compares two RelationalObjects within the same class hierarchical
     * branch for semantic ordering. The comparison may be based upon any of
     * the class state elements so long as the compareTo() method contract is
     * not broken.
     *
     * @param upper The RelationalObject within the same heirarchical branch
     *              and with lesser definition to be compared.
     *
     * @return An int value representing the semantic relationship between the
     *         two RelationalObjects.
     */
    protected abstract int compareToSuperType(RelationalObject upper);
}
于 2012-08-01T05:44:53.003 回答