简体   繁体   English

实施可比 <T> 在通用超类中

[英]Implement Comparable<T> in a generic superclass

I have an abstract generic superclass which I extend to make concrete classes with IDs of a specific type: 我有一个抽象的泛型超类,将其扩展为使用特定类型ID的具体类:

public abstract class AbstractEntity<I> {
  ...
  private I id;
  private String name;
  ...
}

I create the concrete classes like this: 我创建如下具体类:

public class User extends AbstractEntity<Long> {...}

Now I want to make the concrete classes comparable to other instances of themselves (and no other type--this should be enforced at compile time). 现在,我想使具体类与自己的其他实例可比(而不是其他类型,这应在编译时强制执行)。 By default the compareTo method should just sort by name so I want to add it in the superclass to avoid repeating code. 默认情况下, compareTo方法应仅按名称排序,所以我想将其添加到超类中以避免重复代码。 The only way I've come up with to do this is with this ugly construct: 我想到的唯一方法是使用这个丑陋的结构:

public abstract class AbstractEntity<I,T> implements Comparable<AbstractEntity<I,T>> {
  ...
  private I id;
  private String name;
  ...
  @Override
  public int compareTo(AbstractEntity<I,T> o) {
    ...
  }
}

... ...

public class User extends AbstractEntity<Long,User> {...}

I think this is ugly because now in order to extend the superclass you need to repeat the concrete class name again as a type parameter for itself, which is odd and counterintuitive. 我认为这很丑陋,因为现在要扩展超类,您需要再次重复具体的类名作为其自身的类型参数,这是奇怪且违反直觉的。 Is there a more elegant way to accomplish the same thing that I'm missing? 有没有更优雅的方式来完成我所缺少的事情?

Thanks! 谢谢!

What you're looking for is the "self type", but this can't be achieved in Java. 您正在寻找的是“自我类型”,但这在Java中无法实现。 The closest you can come is using a recursively bound type parameter that is supposedly the self type: 您可以使用的最接近的方法是使用递归绑定的类型参数,该参数应该是自身类型:

public abstract class AbstractEntity<I, E extends AbstractEntity<I, E>> implements Comparable<E> {
    ...
    private I id;
    private String name;
    ...
    public final String getName() {
        return name;
    }
    ...
    @Override
    public int compareTo(E otherEntity) {
        final String otherName = otherEntity.getName();
        ...
    }
}

public final class User extends AbstractEntity<Long, User> { }

I would recommend against this pattern though, as it's confusing and can easily be abused. 但我还是建议您不要使用这种模式,因为它很容易混淆并且容易被滥用。 For example: 例如:

public final class EvilUser extends AbstractEntity<Long, AnotherUser> { }

My advice: just stick to implementing Comparable on an individual-entity basis. 我的建议:仅坚持在个体实体上实施Comparable

No. This is how you're supposed to do it. 不,这是您应该这样做的方式。 Putting the class itself in the parameter description is actually a normal thing to do in a situation like this one. 在这种情况下,将类本身放入参数描述中实际上是正常的事情。

Is this what you are looking for 这是你想要的

public abstract class AbstractEntity<I> implements
        Comparable<AbstractEntity<I>> {
    private I id;

    @Override
    public int compareTo(AbstractEntity<I> o) {

        if (o != null && !o.getClass().equals(getClass())) {
            throw new IllegalArgumentException("Unsupported instance type "
                    + o.getClass());
        }

        return 0;
    }

}

public class User extends AbstractEntity<Long> {
}

Now I want to make the concrete classes comparable to other instances of themselves (and no other type--this should be enforced at compile time). 现在,我想使具体类与自己的其他实例可比(而不是其他类型,这应在编译时强制执行)。

Why? 为什么? Generics is not there for you to make arbitrary restrictions. 泛型不存在您可以进行任意限制的地方。 Generics is only for enforcing type safety (ie the elimination of casts; avoiding ClassCastException). 泛型仅用于强制类型安全 (即消除强制类型转换;避免ClassCastException)。 Arbitrarily requiring it to not be comparable to other types serves no type-safety purpose, and thus cannot be done. 任意要求它与其他类型不具有可比性,没有任何类型安全目的,因此无法实现。

If the comparison does not depend on any subclass features, then AbstractEntity<I> is comparable to all AbstractEntity<I> , in which case it should be declared like this: 如果比较不依赖于任何子类功能,则AbstractEntity<I>可与所有AbstractEntity<I>相比较,在这种情况下,应这样声明:

public abstract class AbstractEntity<I> implements Comparable<AbstractEntity<I>>

The problem here is that the concrete class would be comparable with any other concrete class with the same ID type at compile time 这里的问题是,在编译时,具体类将与具有相同ID类型的任何其他具体类相提并论

So what? 所以呢? The comparison is perfectly type-safe. 比较是完全类型安全的。 If you don't want to compare one concrete class to another, then don't. 如果您不想将一个具体的类与另一个具体的类进行比较,那就不要。 If someone else wants to compare one concrete class to another, then great for them. 如果其他人想将一个具体的课程与另一个具体的课程进行比较,那么对他们很有帮助。 Why does this matter to you? 为什么这对您很重要?

ps The code you posted, public abstract class AbstractEntity<I,T> implements Comparable<AbstractEntity<I,T>> also does not enforce that one class only compares to itself, because there is no guarantee that a class must extend it with itself as the second parameter. ps您发布的代码, public abstract class AbstractEntity<I,T> implements Comparable<AbstractEntity<I,T>>也不强制一个类仅与自身进行比较,因为不能保证一个类必须对其自身进行扩展作为第二个参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM