Dominic Mortlock
Dominic Mortlock

Reputation: 284

Specific Java inheritance inquiry - Need suggestions

The problem I am having is quite specific, and a bit difficult to explain. Let me know if you need more details about anything. I have an abstract class called System. To hold my System objects, I have a SystemManager which contains an list of Systems, and some functions for manipulating it. Inside it contains:

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

Now, I want to create another abstract class which is a specific type of System called RenderSystem. This will inherit from System but have a few more functions. I also want to create a RenderSystemManager which should do everything SystemManager does, except with a few extra features. Also, instead of having a list of System in the manager, I would like it to have a list of RenderSystem to ensure that the programmers don't put any regular System objects in it. My initial instinct was to inherit SystemManger, and just change the type of the list to RenderSystem:

systems = new ArrayList<RenderSystem>();

Java doesn't allow this as systems is type System not RenderSystem. I would have assumed it would be OK considering RenderSystem inherits from System. One way I can think of to resolve this issue is to copy and paste all the code from SystemManager into RenderSystemManager and just change the line of code to be:

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

My other instinct would be to override the addSystem(System system) function to ensure that it only handles RenderSystem, but the programmers might think they are allowed to do it even if it doesn't work.

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

These doesn't seem very elegant though. Anybody have any suggestions?

Upvotes: 0

Views: 62

Answers (3)

arcy
arcy

Reputation: 13123

Your SystemManager could have a a list of System objects, and the list could be private, and the only way to add an object to that list would be a function that only took a RenderSystem as an argument. You're trying to manhandle generics into a use for which they probably are not appropriate.

But I think you have bigger problems.

I think this happens to many of us when we start trying to design "from the inside out", i.e., you are taking programming constructs and trying to string them together at a level of detail that ignores (or forgets) what the code is trying to do from a higher level. It's like saying "I want a while loop inside a do loop that has a switch statement with try-catch-finally-whatever, but I don't want to nest all these damn braces."

Take a few steps back and think about the external functionality you want to accomplish, and progress in small steps through design and implementation details from there...

Upvotes: 0

JB Nizet
JB Nizet

Reputation: 691735

Your managers have the same type-safety requirements as the list they wrap. They should thus follow the same strategy, and be generic types:

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
}

Upvotes: 5

Douglas Jones
Douglas Jones

Reputation: 2542

I think your second instinct to add protection into the addSystem call is the correct one. That way SystemManager can still operate on the list of Systems. However I would change the implementation of addSystem to instruct developers in the proper usage:

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

Upvotes: 0

Related Questions