我遇到的问题非常具体,而且有点难以解释。如果您需要更多有关任何细节,请与我们联系我有一个名为System
的抽象类。为了保存我的System
个对象,我有一个SystemManager
,其中包含System
的列表,以及一些用于操作它的函数。里面包含:
List<System> systems = new ArrayList<System>();
现在,我想创建另一个抽象类,它是System
的一种特定类型RenderSystem
。这将继承自System
,但还有一些功能。我还想创建一个RenderSystemManager
,它应该完成SystemManager
所做的一切,除了一些额外的功能。此外,我希望管理器中没有System
列表,而是希望程序员不会在其中放置任何常规RenderSystem
对象。我的初衷是继承System
,只需将列表类型更改为SystemManger
:
RenderSystem
Java不允许这样做,因为系统类型为systems = new ArrayList<RenderSystem>();
而不是System
。考虑到RenderSystem
继承自RenderSystem
,我认为可以。我可以想到解决此问题的一种方法是将System
中的所有代码复制并粘贴到SystemManager
中,然后将代码行更改为:
RenderSystemManager
我的另一个本能是覆盖List<RenderSystem> systems = new ArrayList<RenderSystem>();
函数以确保它只处理addSystem(System system)
,但程序员可能会认为即使它不起作用也允许它们执行。
RenderSystem
但这些似乎并不优雅。有人有什么建议吗?
答案 0 :(得分:5)
您的经理与他们包装的列表具有相同的类型安全要求。因此,他们应遵循相同的策略,并且是通用类型:
public class BaseSystemManager<T extends System> {
private List<T> systems = new ArrayList<>();
public void addSystem(T system) {
systems.add(system);
}
// common methods
}
public class SystemManager extends BaseSystemManager<System> {
// methods specific to System handling
}
public RenderSystemManager extends BaseSystemManager<RenderSystem> {
// methods specific to RenderSystem handling
}
答案 1 :(得分:0)
我认为你在addSystem调用中添加保护的第二直觉是正确的。这样,SystemManager仍然可以在系统列表上运行。但是,我会更改addSystem的实现,以指示开发人员正确使用:
@Override
public void addSystem(System system)
{
if (system instanceof RenderSystem)
{
super.addSystem(system);
}
else
{
throw new IllegalArgumentException("Only RenderSystem objects can be added to a RenderSystemManager");
}
}
答案 2 :(得分:0)
您的SystemManager可以有一个System对象列表,列表可以是私有的,将对象添加到该列表的唯一方法是只将RenderSystem作为参数的函数。你试图将泛型用于他们可能不合适的用途。
但我认为你有更大的问题。
我认为当我们开始尝试“从内到外”设计时,我们很多人都会遇到这种情况,即,您正在采用编程结构并尝试将它们串联在一起,忽略(或忘记)什么代码正试图从更高层次做。这就像是说“我想在一个do循环中有一个while循环,它有一个带有try-catch-finally-then的switch语句,但我不想嵌套所有这些该死的大括号。”
回过头来考虑一下你想要完成的外部功能,并从那里通过设计和实现细节的小步骤前进......