Emma Thierry
Emma Thierry

Reputation: 31

Get subclass from super class constructor

I have an X class that does stuff. There can be multiple kinds of X. Usually I'd just do a subclass for each type, but there is a part of my program that I can't change that declares and instantiates an X with the X constructor. I have total control on X, except for the constructor signature. (which is called by the part of my program I can't change)

I thought about making an Xcontroller for each type that contains the methods I want to override and are stored in X. Some methods require the use of super methods of X and unless I'm mistaken, I can't call them from another class.

Example code:

class cantTouchThis{
    public static void main(String[] args){
        // Can't change this
        X x = new X("obligatory parameter");
        doThings(x);
    }

    private static void doThings(X x){
        // do stuff with X
    }
}

enum Type{
    A, B, C;
    public static Type iKnowHowToGetTheTypeTrustMe(){
        // Always return the good type for the instance
    }
}

class X extends SuperClass {
    public X(String string){
        Type type = Type.iKnowHowToGetTheTypeTrustMe();
    }

    public void a(Object one, Object two){
        switch(type){
            case A:
                super.a(one, two);
                return;
            case B:
                doOtherThings(one, two);
                return;
            case C:
                super.a(two, one);
                return;
        }
    }

    private void doOtherThigns(Object one, Object two){
        // stuff
    }
}

I'd rather make the type their own classes (class A extends X, class B extends X, class C extends X). But I have to use the code in cantTouchThis which always declares an X and instantiates with the X constructor. The X class has a ton of switch cases, and a lot of instance variables used only for certain types and useless the rest of the time.

Is there a way to make the X constructor change it's own type and become one of it's subclasses ?

Upvotes: 3

Views: 572

Answers (3)

Emma Thierry
Emma Thierry

Reputation: 31

So it seem I can't change the constructor the way I want (thanks @JoakimDanielson) I found a way to use controllers:

If I create a superA method in X that just call the super method, it can be called from the controller.

Exemple code:

class X extends SuperClass {
    private final Controller controller;

    public X(String string){
        Type type = iKnowHowToGetTheTypeTrustMe();
        switch(type) {
            case A:
                controller = new AX(this);
                break;
            case B:
                controller = new BX(this);
                break;
            // and so on...
        }
    }

    public void superA(Object one, Object two){
        super.a(one, two);
    }

    public void a(Object one, Object two){
        controller.a(one, two);
    }
}

class Controller {
    private X x;
    public Controller(X x) {this.x = x;}
    public getX(){...}
}

class AX extends Controller {
    public void a(Object one, Object two) {
        getX().superA(one, two);
    }
}

Thanks for your help, if there is a cleaner/better way please tell me.

Upvotes: 0

Tobias Wichtrey
Tobias Wichtrey

Reputation: 1218

You could use a delegate. Something like this:

class X extends SuperClass {

    private final SuperClass delegate;

    public X(String string){
        Type type = Type.iKnowHowToGetTheTypeTrustMe();
        switch(type) {
            case A:
                delegate = new AX(string);
                break;
            case B:
                delegate = new BX(string);
                break;
            // and so on...
        }
    }

    public void a(Object one, Object two) {
        delegate.a(one,two);
    }
}

And then implement a in AX, BX, CX as you like.

Upvotes: 1

ControlAltDel
ControlAltDel

Reputation: 35011

You can use the factory pattern. (example: https://sourceforge.net/p/tus/code/HEAD/tree/tjacobs/io/ServerSocketEx.java)

In ServerSocketEx, there is a SocketRunnerFactory. SocketRunnerFactory is an interface for creating SocketRunners. So every time the ServerSocket accepts a new connection, it gets a new SocketRunner from the factory. And you can create your own ServerRunnerFactory to handle the Socket however you want

You'd use this pattern to created subclasses of X's.

Upvotes: 1

Related Questions