compareTo和继承

时间:2018-04-13 19:06:54

标签: java generics inheritance comparable compareto

所以我的泛型代码有问题。我创建了类Person,Student扩展了Person。当我试图比较两个学生时,它突然认为它是一个人,甚至没有包括组号。这是我的Person类

public class Person implements Comparable<Person>{...
        public int compareTo(Person o) {
        if(this.name.compareTo(o.name) > 0 )
            return 1;
        else if(this.name.compareTo(o.name) < 0)
            return -1;
        else{
            if(this.age > o.age)
                return 1;   
            else if(this.age < o.age)
                return -1;
            else{
                return 0;}
        }
}

我的学生,其中compareTo似乎非常相似,但附加了组ID

public class Student extends Person implements Comparable<Person>{
      public int compareTo(Student s) {

    if(this.name.compareTo(s.name) > 0 ){
        System.out.println(this + " > " + s);
        return 1;}

    else if(this.name.compareTo(s.name) < 0){
        System.out.println(this + " < " + s);
        return -1;}

    else{
        if(this.age > s.age){
            System.out.println(this + " > " + s);
            return 1;}

        else if(this.age < s.age){
            System.out.println(this + " < " + s);
            return -1;}

        else{
            if(groupId > s.groupId){
                System.out.println(this + " > " + s);
                return 1;
            }
            else if(groupId < s.groupId){
                System.out.println(this + " < " + s);
                return -1;}
            else{
                System.out.println(this + " = " + s);
                return 0;}

        }   
            } 
        }

最后是一个Box类,它使用泛型来查找这些类和其他类型的最大值和最小值。

    public class Box<T extends Comparable> extends ArrayList<T> {

public T min() {
            T t = get(0);   

            for(int i = 0; i < this.size(); i++){
                    if(t.compareTo(get(i)) > 0)
                        t = super.get(i);
                    }   
            return t;
        }
    }

我没有向您展示整个代码,但我认为这已经足够了。我已经制作了Box对象,但仍将它们作为Person而不是Student进行比较。 谁能解释一下这里的问题是什么? 编辑:我的数组

Box<Student> bst = new Box<>();
        bst.add(new Student("Nowacka", 24, 100));        
        bst.add(new Student("Nowacka", 24, 300));
        bst.add(new Student("Nowacka", 24, 200));
        bst.print();
        System.out.println(bst.max());                                          // Student: Nowacka, 24, 300

答案应该是300,但是是100并且在人的比较中我已经添加了一些System.out.println以查看它正在使用的方法

2 个答案:

答案 0 :(得分:1)

让我们分析Comparable<T>实际需要和做的事情。如果SomeClass implements Comparable<T>,您将被迫实施方法public int compareTo(T other)T将在一秒钟内变得重要,保持在他的脑后。这就是您对Person - 类所做的事情:

public class Person implements Comparable<Person> {
    // ...
    public int compareTo(Person o) {
    if (this.name.compareTo(o.name) > 0 ) {
        return 1;
    } else if (this.name.compareTo(o.name) < 0) {
        return -1;
    }
    else {
        if (this.age > o.age) {
            return 1;   
        } else if (this.age < o.age) {
            return -1;
        } else {
            return 0;
        }
    }
}

现在,让我们检查Student - 类:

public class Student extends Person implements Comparable<Person>{
    public int compareTo(Student s) { 
        ...
    }
}

我们实施Comparable<Person>,但我们没有public int compareTo(Person p),我们只有public int compareTo(Student s)。那为什么要编译呢?因为我们从public int compareTo(Person p)继承Person。方法public int compareTo(Student s)实际上从未使用过,至少在Comparable<Person>接口的上下文中没有使用过。

那么,让我们public class Student extends Person implements Comparable<Student>!遗憾的是,编译器不喜欢这样。我们不能使用不同的类型参数多次实现相同的通用接口。我们被卡住。只要在对象层次上实现Comparable,我们就无法重新实现它。

很有可能覆盖compareTo(...)方法。但是,这将违反Comparable

的合同
  

实施者必须确保所有sgn(x.compareTo(y)) == -sgn(y.compareTo(x))x y。 (这意味着如果x.compareTo(y)抛出异常,y.compareTo(x)必须抛出异常。)

     

实现者还必须确保关系具有传递性:(x.compareTo(y) > 0 && y.compareTo(z) > 0)隐含x.compareTo(z) > 0

     

最后,实施者必须确保x.compareTo(y) == 0隐含所有sgn(x.compareTo(z)) == sgn(y.compareTo(z))的{​​{1}}。

让我们尽量不破坏合同。 z类的可能实现可能如下所示:

Student

但是这个解决方案也打破了// CAUTION! This implementation is BROKEN! Keep reading to learn why. public class Student extends Person { @Override public int compareTo(Person that) { int comp = super.compareTo(that); if (comp == 0 && that instanceof Person == true) { Student thatStuden = ((Student) that); comp = ... } return comp; } } 合同的一部分:

  

最后,实施者必须确保Comparable隐含所有x.compareTo(y)==0的{​​{1}}。

以不太正式的方式说,如果sgn(x.compareTo(z)) == sgn(y.compareTo(z))z两件事相等(x),那么我是否比较{{1}并不重要或y或其他内容,结果必须相同(x.compareTo(y) == 0 1 )。&#34;

我们怎样才能打破它?我们假设我们有两个x s yx.compareTo(z) == y.compareTo(z) Student。让我们进一步假设我们有s1s2s1.compareTo(s2) != 0。由于p3p3.compareTo(s1) == 0,合同要求p3.compareTo(2) == 0。这是一个矛盾。

Comparator<T>的形式有另一种选择。您将排序条件与实际对象分开。

对于您的示例,它可能如下所示:

p3.compareTo(s1) == 0

<强>确认

我最初认为应该可以以不违反合同的方式转发p3.compareTo(s2) == 0。但@ user2357112教我相反=)。谢谢你指出我的两个错误!

1 为了便于阅读,我忽略了s1.compareTo(s2) == 0

答案 1 :(得分:0)

我认为它们将它们比作Person,因为您已在Comparable<Person>类中实施Student

public class Student extends Person implements Comparable<Person>

尝试替换

public class Student extends Person implements Comparable<Student>