从超类构造函数获取子类

huangapple go评论96阅读模式
英文:

Get subclass from super class constructor

问题

我有一个执行操作的 X 类。可以有多种类型的 X。通常我会为每种类型做一个子类,但是我程序中的一部分我无法更改,它使用 X 构造函数声明和实例化 X。除了构造函数的签名外,我对 X 有完全的控制权(构造函数被我无法更改的程序部分调用)。

我考虑为每种类型创建一个 Xcontroller,其中包含我想要重写的方法并存储在 X 中。某些方法需要使用 X 的 super 方法,除非我弄错了,我不能从另一个类调用它们。

示例代码:

class cantTouchThis {
    public static void main(String[] args) {
        // 不能更改这部分
        X x = new X("必需的参数");
        doThings(x);
    }

    private static void doThings(X x) {
        // 使用 X 进行操作
    }
}

enum Type {
    A, B, C;

    public static Type iKnowHowToGetTheTypeTrustMe() {
        // 总是返回实例的正确类型
    }
}

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) {
        // 操作
    }
}

我更愿意将不同类型作为它们自己的类(类 A 扩展 X,类 B 扩展 X,类 C 扩展 X)。但是我必须使用 cantTouchThis 中的代码,它总是声明一个 X 并使用 X 构造函数实例化。X 类中有大量的 switch 语句和许多实例变量,只用于特定类型,在其余时间无用。

是否有办法使 X 构造函数改变自己的类型,并成为它的子类之一?

英文:

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 ?

答案1

得分: 1

你可以使用工厂模式。(示例:https://sourceforge.net/p/tus/code/HEAD/tree/tjacobs/io/ServerSocketEx.java)

在ServerSocketEx中,有一个SocketRunnerFactory。SocketRunnerFactory是用于创建SocketRunner的接口。因此,每当ServerSocket接受新连接时,它都会从工厂获得一个新的SocketRunner。而且你可以创建自己的ServerRunnerFactory来处理Socket,以任何你想要的方式。

你会使用这个模式来创建X的子类。

英文:

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.

答案2

得分: 1

你可以使用委托(delegate)。类似这样:

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;
            // 以此类推...
        }
    }

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

然后在 AX、BX、CX 中根据你的需要实现 a 方法。

英文:

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.

答案3

得分: 0

以下是您要求的翻译内容:

所以似乎我无法按照我想要的方式更改构造函数(感谢 @JoakimDanielson)
我找到了一种使用控制器的方法:

如果我在 X 中创建一个名为 superA 的方法,只需调用 super 方法,它可以从控制器调用。

示例代码:

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;
			// 依此类推...
		}
	}
	
	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);
	}
}

感谢您的帮助,如果有更清晰/更好的方法,请告诉我。

英文:

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.

huangapple
  • 本文由 发表于 2020年4月7日 19:34:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/61079119.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定