0

我有一个抽象的通用超类,我扩展它以创建具有特定类型 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> {...}

我认为这很丑,因为现在为了扩展超类,您需要再次重复具体的类名作为其自身的类型参数,这很奇怪且违反直觉。有没有更优雅的方式来完成我所缺少的相同的事情?

谢谢!

4

4 回答 4

7

What you're looking for is the "self type", but this can't be achieved in 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.

于 2013-04-26T04:51:53.243 回答
2

不,这是你应该这样做的。将类本身放在参数描述中,在这种情况下其实是很正常的事情。

于 2013-04-26T03:15:20.993 回答
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> {
}
于 2013-04-26T03:20:48.213 回答
0

现在我想让具体类与它们自身的其他实例相比较(并且没有其他类型——这应该在编译时强制执行)。

为什么?泛型不是让你任意限制的。泛型仅用于强制类型安全(即消除强制转换;避免 ClassCastException)。任意要求它不能与其他类型进行比较没有任何类型安全的目的,因此无法做到。

如果比较不依赖于任何子类特征,则AbstractEntity<I>可以与 all 进行比较AbstractEntity<I>,在这种情况下,它应该这样声明:

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

这里的问题是具体类在编译时可以与任何其他具有相同 ID 类型的具体类进行比较

所以呢?比较是完全类型安全的。如果您不想将一个具体类与另一个类进行比较,那就不要。如果其他人想将一个具体类与另一个类进行比较,那对他们来说很好。为什么这对你很重要?

ps您发布的代码public abstract class AbstractEntity<I,T> implements Comparable<AbstractEntity<I,T>>也不会强制一个类只与自身进行比较,因为不能保证一个类必须以自身作为第二个参数来扩展它。

于 2013-04-26T18:19:55.697 回答