我目前在一家拥有各种模块的公司工作。在那家公司,如果你想提供模块内部,你可以通过java接口提供它,它隐藏了实际的实现类型,并为请求模块提供了一个接口。现在我希望有一个提供程序能够为多个模块提供数据,这些模块公开了实际内部数据的不同字段或方法。
因此我有一个内部Object,它有一些数据,我有一个接口,每个模块需要访问一些但不是严格的所有字段。最后,我有一个外部对象实现所有这些接口,并保存内部对象的实例以委托方法调用:
public class InternalObject {
public int getA() { return 0; }
public int getB() { return 0; }
}
public interface ModuleXObject {
int getA();
}
public interface ModuleYObject {
int getA();
int getB();
}
public class ExternalObject implements ModuleXObject, ModuleYObject {
private InternalObject _internal;
public int getA() { return _internal.getA(); }
public int getB() { return _internal.getB(); }
}
现在这一切都很好,但是如果我想提供 - 让我们说 - 用于查找为正确模块键入的所述对象列表的存储库方法,我遇到了如何实现这一点的问题。我希望得到以下内容:
public interface ModuleXObjectRepository {
List<ModuleXObject> loadAllObjects();
}
public interface ModuleYObjectRepository {
List<ModuleYObject> loadAllObjects();
}
public class ExternalObjectRepository implements ModuleXObjectRepository, ModuleYObjectRepository {
public List<ExternalObject> loadAllObjects() {
// ...
}
}
这不会编译说返回类型不兼容。 所以我的问题是,如果有可能实现类似的东西,如果,如何?
我应该注意到,我尝试了一些不同的方法,我想包括它们的完整性并描绘它们的缺点(在我看来)。
方法1 :
public interface ModuleXObjectRepository {
List<? extends ModuleXObject> loadAllObjects();
}
public interface ModuleYObjectRepository {
List<? extends ModuleYObject> loadAllObjects();
}
public class ExternalObjectRepository implements ModuleXObjectRepository, ModuleYObjectRepository {
public List<ExternalObject> loadAllObjects() {
// ...
}
}
这种方法与我希望的解决方案非常接近,但会产生如下代码:
List<? extends ModuleXObject> objects = repository.loadAllObjects();
因此要求用户包含&#34;?延伸&#34;关于调用loadAllObjects()的每个List-Declaration。
方法2 :
public interface ModuleXObjectRepository {
List<ModuleXObject> loadAllObjects();
}
public interface ModuleYObjectRepository {
List<ModuleYObject> loadAllObjects();
}
public class ExternalObjectRepository implements ModuleXObjectRepository, ModuleYObjectRepository {
public List loadAllObjects() {
// ...
}
}
这种方法只省略了ExternalObjectRepository中的泛型,因此在我看来太过于减少了类型安全性。此外,我还没有测试过这是否真的有效。
只是为了重新编写,是否有任何可能的方法来定义loadAllObjects方法,使用户能够获得使用各自模块的对象键入的列表,而不用
答案 0 :(得分:0)
允许将其键入List<ModuleXObject>
的挑战是其他代码可以保留为List<ExternalObject>
。
所有ExternalObject
个实例都是ModuleXObject
个实例,但反之则不然。
考虑以下附加课程:
public class MonkeyWrench implements ModuleXObject{
//STUFF
}
MonkeyWrench
个实例不是ExternalObject
个实例,但是如果可以将List<ExternalObject>
强制转换为List<ModuleXObject>
,则可以向此集合添加MonkeyWrench
个实例,这样导致运行时类转换异常和废墟类型安全的风险。
其他代码非常容易:
for(ExternalObject externalObject:externalObjectRepository.loadAllObjects())
如果其中一个实例是MonkeyWrench
实例,则运行时类转换,这是泛型要避免的。
? extends ModuleXObject
的含义是你可以从集合中读取任何对象ModuleXObject
但是你不能向集合中添加任何东西,因为其他代码可能对集合有额外的约束。在编译时不明显/可用。
我建议您使用? extends ModuleXObject
,因为它的语义似乎与您想要的一致,即拉出ModuleXObject
个实例,例如。
ModuleXObjectRepository repo = //get repo however
for(ModuleXObject obj : repo.loadAllObjects()){
//do stuff with obj
}