Reputation: 31
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
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
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
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