我有一个抽象的通用超类,我扩展它来制作具有特定类型ID的具体类:
public abstract class AbstractEntity<I> {
...
private I id;
private String name;
...
}
我创建了这样的具体类:
public class User extends AbstractEntity<Long> {...}
现在我想使具体类与其他自己的实例相比(没有其他类型 - 这应该在编译时强制执行)。默认情况下,compareTo
方法应该按名称排序,因此我想将其添加到超类中以避免重复代码。我想出来的唯一方法是使用这个丑陋的构造:
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> {...}
我认为这很难看,因为现在为了扩展超类,你需要再次重复具体的类名作为自身的类型参数,这是奇怪的和违反直觉的。是否有更优雅的方式来完成我所缺少的同样的事情?
谢谢!
答案 0 :(得分:7)
您正在寻找的是“自我类型”,但这在Java中无法实现。你最接近的是使用一个递归绑定的类型参数,该参数应该是自我类型:
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> { }
我会建议不要使用这种模式,因为它很容易混淆,很容易被滥用。例如:
public final class EvilUser extends AbstractEntity<Long, AnotherUser> { }
我的建议:坚持在个人实体的基础上实施Comparable
。
答案 1 :(得分:2)
没有。这就是你应该怎么做的。在类似这样的情况下,将类本身放在参数描述中实际上是正常的事情。
答案 2 :(得分:1)
这就是你要找的东西
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> {
}
答案 3 :(得分:0)
现在我想使具体类与其他实例相媲美 他们自己(没有其他类型 - 这应该在编译时强制执行 时间)。
为什么呢?泛型不适合你进行任意限制。泛型仅用于强制执行类型安全(即消除强制类型转换;避免使用ClassCastException)。任意要求它不能与其他类型相比,不能用于类型 - 安全目的,因此无法完成。
如果比较不依赖于任何子类功能,那么AbstractEntity<I>
可与所有AbstractEntity<I>
相媲美,在这种情况下,它应该像这样声明:
public abstract class AbstractEntity<I> implements Comparable<AbstractEntity<I>>
这里的问题是具体类可以与之相媲美 编译时具有相同ID类型的任何其他具体类
那又怎样?比较完全是类型安全的。如果您不想将一个具体类别与另一个具体类别进行比较,那么请不要。如果其他人想要将一个具体的类别与另一个具体类别进行比较,那么对他为什么这对你很重要?
P.S。您发布的代码public abstract class AbstractEntity<I,T> implements Comparable<AbstractEntity<I,T>>
也没有强制要求一个类仅与自身进行比较,因为无法保证类必须将其自身扩展为第二个参数。