2014-03-02 23 views
0

我遇到的问题很具体,并且有点难以解释。让我知道你是否需要更多关于任何事情的细节。我有一个叫System的抽象类。为了容纳我的System对象,我有一个SystemManager,其中包含System的列表以及一些用于操作它的函数。它里面包含:具体的Java继承查询 - 需要建议

List<System> systems = new ArrayList<System>(); 

现在,我想创建另一个抽象类是所谓的RenderSystemSystem特定类型。这将继承System,但有几个功能。我也想创建一个RenderSystemManager,除了一些额外的功能外,它应该可以做所有的事情SystemManager。另外,我不希望经理中有System的列表,我希望它有一个RenderSystem的列表,以确保程序员不会在其中放置任何常规的System对象。我最初的反应是继承SystemManger,只是更改列表的类型RenderSystem

systems = new ArrayList<RenderSystem>(); 

Java不允许将此作为​​系统的类型是SystemRenderSystem。我会认为考虑RenderSystem继承自System会好的。我能想到的一种方式来解决这个问题是复制和SystemManager所有的代码粘贴到RenderSystemManager,只是改变的代码行是:

List<RenderSystem> systems = new ArrayList<RenderSystem>(); 

我的其他本能会覆盖addSystem(System system)功能确保它只处理RenderSystem,但程序员可能认为即使它不起作用也可以这样做。

@Override 
public void addSystem(System system) 
{ 
    if (system instanceof RenderSystem) 
    { 
     super.addSystem(system); 
    } 
} 

虽然这些看起来不太优雅。任何人有任何建议?

+1

看来你的'想法RenderSystemManager'违反了[ LSP](http://en.wikipedia.org/wiki/Liskov_substitution_principle),因为'SystemManager'允许添加'System's,但其所声称的子类型不会。 – delnan

+1

考虑将您的'System'类的名称更改为不同的避免与'java.lang.System'类冲突 – Pshemo

+0

同意@delnan,但是LSP维基百科页面可能有点迟钝*基本上*,它表明子类不应该从超类中删除*特性,这就是你提出的设计确实如此,我建议你考虑JB Nizet的解决方案b elow。 –

回答

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 
} 
+0

完美。完全是我在找的!我从来没有用过这个,但它实际上对我正在做的其他一些事情有用。非常感谢你。 +1 –

+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"); 
    } 
} 
0

你的SystemManager可以有系统对象的AA列表,该列表可以是私有的,只有这样才能对象添加到该列表会一个仅将RenderSystem作为参数的函数。您试图将泛型转化为可能不适用的用途。

但我认为你有更大的问题。

我认为,当我们开始尝试设计“从内到外”时,就会发生这种情况,也就是说,您正在编程构造并尝试将它们串联在一起,忽略(或忘记)什么细节代码正试图从更高的层面上做。这就像说:“我想要一个while循环内部的do循环,它带有try-catch-finally-switch的开关语句,但是我不想嵌套所有这些该死的大括号。“

采取后退几步,想想你要完成的外部功能和进步,通过从那里设计和实施细节的小步骤...