简体   繁体   English

如何在中间添加抽象类并使用Java调用函数?

[英]How to add an abstract class in the middle with a call to a function using java?

I have the following structure: 我有以下结构:

public abstract class BaseCall<T> implements Callable<T> {

    public abstract T innerCall();

    protected Structure getProxy() {
       return SomeStructure;
    }
}

And at least 4 classes that look like that: 至少有四个类似的类:

public class GetXCall extends BaseCall<Set<String>> {

    private final Credentials credentials;

    public GetXCall (Credentials credentials) {
        this.credentials = credentials;
    }

    @Override
    public Set<String> innerCall() {
        return getProxy().getXfromVC(credentials);
    }

}

public class GetYCall extends BaseCall<Set<String>> {

    private final Credentials credentials;

    public GetYCall (Credentials credentials) {
        this.credentials = credentials;
    }

    @Override
    public Set<String> innerCall() {
        return getProxy().getYfromVC(credentials);
    }
}

I'm trying to figure out how to make it prettier and add another abstract class in the middle so I can just pass the function getYfromVC or getXfromVC and the abstract class will call something like : 我试图弄清楚如何使其更漂亮,并在中间添加另一个抽象类,这样我就可以传递函数getYfromVCgetXfromVC ,并且抽象类将调用类似的内容:

getProxy()._____(credentials)

This is what I tried but it doesn't seem to work as I can't use run inside 这是我尝试过的方法,但是似乎无法正常run因为我无法使用run inside

public abstract class RunVcTask<T> extends BaseCall<T> {

    private final Credentials credentials;

    public RunVcTask(Credentials credentials)    {
        this.credentials = credentials;
    }

    public abstract T run();

    @Override
    public T innerCall() {
        return getProxy().run(credentials); //HERE the run can't work
    }
}

As InnerCall not always uses credentials, I can't change it to abstract innerCall(Credentials c) 由于InnerCall并非始终使用凭据,因此无法将其更改为abstract innerCall(Credentials c)

can someone advise if there is a nice way to do it? 有人可以建议是否有很好的方法吗? (I'm currently using java 7) (我目前正在使用Java 7)

If you stick to inheritance, there is no simplification possible beyond 如果您坚持继承,那么除了简化之外别无他法

public abstract class BaseCall<T> implements Callable<T> {

    public abstract T innerCall();

    protected Structure getProxy() {
       return SomeStructure;
    }
}
public abstract class RunVcTask<T> extends BaseCall<T> {

    private final Credentials credentials;

    public RunVcTask(Credentials credentials) {
        this.credentials = credentials;
    }

    public abstract T actualOp(Structure proxy, Credentials credentials);

    @Override
    public T innerCall() {
        return actualOp(getProxy(), credentials);
    }
}

public class GetXCall extends RunVcTask<Set<String>> {
    public GetXCall(Credentials credentials) {
        super(credentials);
    }

    @Override
    public Set<String> actualOp(Structure proxy, Credentials credentials) {
        return proxy.getXfromVC(credentials);
    }
}
public class GetYCall extends RunVcTask<Set<String>> {
    public GetYCall(Credentials credentials) {
        super(credentials);
    }

    @Override
    public Set<String> actualOp(Structure proxy, Credentials credentials) {
        return proxy.getXfromVC(credentials);
    }
}

A better approach is using delegation : 更好的方法是使用委托

public class RunVcTask<T> extends BaseCall<T> {
    interface ActualTask<T> {
        T actualOp(Structure proxy, Credentials credentials);
    }
    enum BuiltIn implements ActualTask<Set<String>> {
        GetX {
            public Set<String> actualOp(Structure proxy, Credentials credentials) {
                return proxy.getXfromVC(credentials);
            }
        },
        GetY {
            public Set<String> actualOp(Structure proxy, Credentials credentials) {
                return proxy.getYfromVC(credentials);
            }
        },
    }

    private final Credentials credentials;
    private final ActualTask<T> delegate;

    public RunVcTask(Credentials credentials, ActualTask<T> task) {
        this.credentials = credentials;
        this.delegate = task;
    }

    @Override
    public T innerCall() {
        return delegate.actualOp(getProxy(), credentials);
    }
}

Here, no special subclass for GetX , GetY , etc is needed, you can instantiate such a call via 在这里,不需要GetXGetY等特殊的子类,您可以通过实例化此类调用

BaseCall<Set<String>> getXInstance = new RunVcTask<>(credentials, RunVcTask.BuiltIn.GetX);
BaseCall<Set<String>> getYInstance = new RunVcTask<>(credentials, RunVcTask.BuiltIn.GetY);

so the specialization code of a particular function reduces to the four lines within the BuiltIn enum . 因此,特定功能的专业化代码减少到BuiltIn enum内的BuiltIn Only actions with the same return type can be aggregated within such an enum , so you would have to use multiple enum s for different types (they don't need to be nested within RunVcTask ) or use anonymous inner classes instead, which is only slightly bigger: 只有具有相同返回类型的动作才能在这样的enum聚合,因此您将必须对不同类型使用多个enum (它们不必嵌套在RunVcTask ),或者使用匿名内部类代替,这仅需一点点大:

BaseCall<Set<String>> getXInstance = new RunVcTask<>(credentials,
    new RunVcTask.ActualTask<Set<String>>() {
        public Set<String> actualOp(Structure proxy, Credentials credentials) {
            return proxy.getXfromVC(credentials);
        }
    });
BaseCall<Set<String>> getYInstance = new RunVcTask<>(credentials,
    new RunVcTask.ActualTask<Set<String>>() {
        public Set<String> actualOp(Structure proxy, Credentials credentials) {
            return proxy.getYfromVC(credentials);
        }
    });

You could also use anonymous inner classes of RunVcTask in the inheritance example, shortening the code to a similar degree, but the delegation approach also provides you with a road map to Java 8, once you are able to switch: 您还可以在继承示例中使用RunVcTask匿名内部类,将代码缩短到类似的程度,但是一旦能够切换,委托方法还为您提供了通往Java 8的路线图:

BaseCall<Set<String>> getXInstance = new RunVcTask<>(credentials, Structure::getXfromVC);
BaseCall<Set<String>> getYInstance = new RunVcTask<>(credentials, Structure::getYfromVC);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM