我在Java中创建了一个通用接口,以便以类型安全的方式表示某些内容的ID。看起来基本上是这样的:
public interface ID<T extends BaseOfAllIDNeedingObjects> {
long getId();
boolean isConcrete();
}
这不完全是它,但足够接近以用于演示目的。实际的ID号是可以获得的,并且我有各种包装工具可以将long转换成ID的实例,所以我可以检查我是否有ID所代表的对象或者我想要转换回对象的包装器。这对单个对象很有用,但问题是至少有一些对象继承了其他对象,并且存在使用基本类型而不是特定类型的情况。例如:
public class SpecificThing extends BaseThing {
/* stuff */
}
public class BaseThing extends BaseOfAllIDNeedingObjects {
/* stuff that all Things need */
}
当然,我希望能够在不同情况下代表BaseThing和SpecificThing的ID。获取SpecificThing需要额外的工作来从数据库中的不同表中提取数据,所以有时我只想要一个BaseThing,因为它具有我当时需要的所有信息。但是,Java不允许以下内容:
public class BaseThing extends BaseOfAllIDNeedingObjects implements ID<BaseThing> {
/* base thing stuff here */
}
public class SpecificThing extends BaseThing implements ID<SpecificThing> {
/* specific things */
}
这是编译器错误。我的IDE(Jetbrains)说&#34; ID不能通过不同的类型参数继承;&#39; BaseThing&#39;和&#39; SpecificThing&#39;&#34;。有什么方法可以解决这个问题吗?我是否只需要不使用ID标记BaseThing,并且只允许将SpecificThings用作ID,将BaseThings包装在单独的ID对象中?或者是否有一些我不知道的模式可以让我将这样的东西运用到工作中?
答案 0 :(得分:3)
您可以将BaseThing
的实现拉到抽象类,然后使用自递归泛型参数:
public abstract class AbstractBaseThing<T extends AbstractBaseThing<T>> extends BaseOfAllIDNeedingObjects implements ID<T> {
/* base thing stuff here */
}
public class BaseThing extends AbstractBaseThing<BaseThing> {
/* concrete base thing */
}
public class SpecificThing extends AbstractBaseThing<SpecificThing> {
/* specific things */
}
答案 1 :(得分:0)
您可以这样定义您的课程:
public class BaseThingGeneric<T extends BaseThingGeneric<T>> extends BaseOfAllIDNeedingObjects implements ID<T> {
/* base thing stuff here */
}
public class BaseThing extends BaseThingGeneric<BaseThing> {
/* just redefine the constructors */
}
public class SpecificThingGeneric<T extends SpecificThingGeneric<T>> extends BaseThingGeneric<T> {
/* specific things */
}
public class SpecificThing extends SpecificThingGeneric<SpecificThing> {
/* just redefine the constructors */
}
实现将在BaseThingGeneric和SpecificThingGeneric中。 提供BaseThing和SpecificThing只是为了简化实例化。 此外,通过扩展SpecificThingGeneric,ScecificThing也可以以相同的方式扩展。