在Java中对子类进行排序 [英] Sorting a subclass in Java

查看:90
本文介绍了在Java中对子类进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设一个 Superclass实现了Comparable< Superclass> ,这样 Arrays.sort(ArrayOfSuperInstances); 使用这个 compareTo(Superclass other)排序方法。这是否保证 Subclass扩展超类的实例数组将使用 Arrays.sort(ArrayOfSubInstances); ? (假设compareTo在子类定义中没有重载)



或换句话说,默认情况下将 Subclass 继承其超类 compareTo 方法,以便可以盲目地使用 Arrays.sort() 知道它们将被分类为超类吗?

解决方案

是的 - 这就是整个原则多态性背后,特别是 Liskov替代原则。基本上,如果A是B的子类,那么你应该能够在任何你能够使用B的地方使用A,并且它应该基本上与B的任何其他实例(或B的其他子类)相同。 / p>

因此,它不仅会发生,而且几乎总是你想要发生的事情。在子类中 compareTo 通常是错误的。



为什么?好吧, Comparable< T> 合同的一部分是该比较是可传递的。由于你的超类可能不知道它的子类正在做什么,如果一个子类以这样的方式覆盖 compareTo ,它给出的答案不同于它的超类,它就会破坏合同。



例如,假设你有像Square和ColorSquare这样的东西。 Square的 compareTo 比较两个方块的大小:

  @Override 
public int compareTo(Square other){
return this.len - other.len;
}

...而ColorSquare也添加颜色比较(让我们假设颜色是可比)。 Java不会让你拥有ColorSquare工具 Comparable< ColorSquare> (因为它的超类已经实现 Comparable< Square> ) ,但你可以使用反射来解决这个问题:

  @Override 
public int compareTo(Square other){
int cmp = super.compareTo(other);
//不要这样做!
if(cmp == 0&&(colorofquare的其他实例)){
ColorSquare otherColor =(ColorSquare)其他;
cmp = color.compareTo(otherColor.color);
}
返回cmp;
}

一开始这看起来很无辜。如果两个形状都是ColorSquare,它们将在长度和颜色上进行比较;否则,他们只会在长度上进行比较。



但如果你有以下内容:

  Square a = ... 
ColorSquare b = ...
ColorSquare c = ...

断言a.compareTo(b)== 0; //假设这个和另一个断言成功
断言a.compareTo(c)== 0;
//传递性意味着b.compareTo(c)也是0,但可能是
//它们具有相同的长度但颜色不同!
断言b.compareTo(c)== 1; //合同坏了!


Suppose a Superclass implements Comparable<Superclass>, such that Arrays.sort(ArrayOfSuperInstances); uses this compareTo(Superclass other) method to sort. Does this guarantee that an array of instances of Subclass extends Superclass will sort in the same way using Arrays.sort(ArrayOfSubInstances); ? (Assuming the compareTo is not overloaded in the subclass definition)

Or in other words, will Subclass by default inherit the compareTo method of its Superclass , so that one can blindly use Arrays.sort() knowing they will be sorted as superclasses would be?

解决方案

Yes -- that is the whole principle behind polymporphism, and specifically the Liskov substitution principle. Basically, if A is a subclass of B, then you should be able to use A anywhere you'd be able to use B, and it should essentially act the same as any other instance of B (or other subclasses of B).

So, not only will it happen, but it's almost always what you want to happen. It's usually wrong to compareTo in the subclass.

Why? Well, part of the Comparable<T> contract is that comparison is transitive. Since your superclass will presumably not know what its subclasses are doing, if a subclass overrides compareTo in such a way that it gives an answer different than its superclass, it breaks the contract.

So for instance, let's say you have something like a Square and a ColorSquare. Square's compareTo compares the two squares' sizes:

@Override
public int compareTo(Square other) {
    return this.len - other.len;
}

...while ColorSquare also adds a comparison for color (let's assume colors are Comparable). Java won't let you have ColorSquare implement Comparable<ColorSquare> (since its superclass already implements Comparable<Square>), but you can use reflection to get around this:

@Override
public int compareTo(Square other) {
    int cmp = super.compareTo(other);
    // don't do this!
    if (cmp == 0 && (other instanceof ColorSquare)) {
        ColorSquare otherColor = (ColorSquare) other;
        cmp = color.compareTo(otherColor.color);
    }
    return cmp;
}

This looks innocent enough at first. If both shapes are ColorSquare, they'll compare on length and color; otherwise, they'll only compare on length.

But what if you have:

Square a = ...
ColorSquare b = ...
ColorSquare c = ...

assert a.compareTo(b) == 0;  // assume this and the other asserts succeed
assert a.compareTo(c) == 0;
// transitivity implies that b.compareTo(c) is also 0, but maybe
// they have the same lengths but different color!
assert b.compareTo(c) == 1; // contract is broken!

这篇关于在Java中对子类进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆