Extending a class that is instantiated by another class
Asked Answered
S

3

8

I'm working with a Java API used for "macros" that automate a piece of software. The API has, among other things, the classes Simulation (a global state of sorts) and FunctionManager. There's nothing I can do to modify these classes.

I'd like to make a BetterFunctionManager class that extends FunctionManager because the latter lacks some useful features. But I don't know how to do this, because FunctionManager can't be instantiated directly. It must be gotten from Simulation, like this:

Simulation simulation = getCurrentSimulation();
FunctionManager functionManager = simulation.getFunctionManager();

Note that Simulation can't be instantiated directly either; it must be gotten via getCurrentSimulation() (the current simulation is determined at runtime by the macro interpreter).

I can't downcast; the following throws a ClassCastException:

BetterFunctionManager betterFunctionManager = simulation.getFunctionManager();

How can I construct BetterFieldFunctionManager?

Sahaptin answered 29/5, 2013 at 12:37 Comment(4)
You could make a class that contains a Simulation attribute, and work your way into all the methods to redefine. You can then have it return your BetterFunctionManager.Praenomen
does FunctionManager expose all members as public which you need in BetterFieldFunctionManager? Or do you need access to protected members also?Fanchette
@Andreas: yes, as far as I know, everything I need is public.Rodger
@Jean-FrançoisCorbett The reason I was asking was to see whether you can use a delegation approach :-) This would also have been my suggestion, as the answers below already propose.Fanchette
S
4

Disclaimer: I am still very naive about designing. Just a suggestion. use delegation design pattern

public class BetterFunctionManager{
    private FunctionManager fm;
    public  BetterFunctionManager(FunctionManager fm){
        this.fm = fm;
    }

    existingMethods(){
        fm.existingMethods();
    }

    newMethods(){
        // new implementation
    }
}

Disadvantages:

need to wrap all methods of FunctionManager

Advantage:

there is no need to change in any other place . just change like

BetterFunctionManager betterFunctionManager = 
                 new BetterFunctionManager (simulation.getFunctionManager());
Stantonstanway answered 29/5, 2013 at 13:16 Comment(4)
Quite a good idea indeed, this mechanism is called delegation. ;) It applies the principle of favoring composition over inheritance.Ashe
@Ashe .. thanks. yes it is delegation pattern... :) .... en.wikipedia.org/wiki/Delegation_patternStantonstanway
This is what I have already implemented. I was hoping to be able to extend rather than delegate, because I don't want to write wrapper methods for all the existingMethods. But thanks for confirming that this is a valid way forward.Rodger
The need to write wrapper methods can be a bit tedious indeed - if you are using Eclipse, there is a code assistent which allows to simply checkmark the desired methods, and Eclipse writes the delegate methods for you (similar feature might exist for Netbeans and others). In any case, using delegation is a very valid approach in this situation.Fanchette
R
2

What you have found is known as The Expression Problem and I'm afraid your most reasonable option to attack it with pure Java is StinePike's proposal of using composition and delegation

If you are in position to choose the tool for the task then I'd recommend you to take a look at Clojure Protocols. They offer a really nice solution to the expression problem (see very good explanation here Solving the Expression Problem with Clojure) and if I'm not mistaken if you end up coding your solution in clojure you can compile it into a java .class and use it in your java app

Recruit answered 29/5, 2013 at 15:2 Comment(1)
Thanks for putting a name on my problem. Excellent article you link to. In a way it's nice to know that this is a problem for everyone, not just me not being able to figure this out!Rodger
R
1

As your options are limited due to the class structures, how about creating a FunctionManagerUtility class instead of BetterFunctionManager. In FunctionManagerUtility class you can add methods to add your useful features by taking FunctionManager object as an input.

Religion answered 29/5, 2013 at 12:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.