首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何为多接口继承启用类似于生成器的模式?

如何为多接口继承启用类似于生成器的模式?
EN

Stack Overflow用户
提问于 2021-01-08 21:21:47
回答 2查看 144关注 0票数 1

首先,让我们定义我们的接口:

代码语言:javascript
复制
public interface Transformable<T> {
    <R extends Transformable<T>> R registerTransformation(Function<T,T> transformation);
    T process(T entity);
}
代码语言:javascript
复制
public interface HttpService<T> {
    T execute(URL url);
}

正如在接口Transformable<T>中所看到的,我们可以创建一个简单的构建器模式来注册转换并在一行中执行它们,例如:

代码语言:javascript
复制
new DefaultTransformableImpl<Integer>(){}
    .registerTransformation(number -> number * 2)
    .registerTransformation(number -> number - 1)
    .registerTransformation(number -> number * number)
    .process(109845)

好了,现在我们准备好创建HttpService的实现了。这样做的目的是提供修改报头的可能性,HTTP方法.在实际向服务器发送请求之前,不需要为org.jsoup.Connection接口指定方法适配器:

代码语言:javascript
复制
import java.util.function.Function;
import java.util.List;
import java.net.URL;
import org.jsoup.Connection;
import org.jsoup.helper.HttpConnection;
import org.jsoup.nodes.Document;
import lombok.SneakyThrows;

public class JsoupHttpService implements HttpService<Document>, Transformable<Connection> {
    private final List<Function<Connection, Connection>> fns = new LinkedList<>();

    @Override public <R extends Transformable<Connection>> R registerTransformation(Function<Connection, Connection> transformation) {
        this.fns.add(transformation);
        return (R) this;
    }

    @Override public Connection process(Connection connection) {
        return fns.stream().reduce(Function.identity(), Function::andThen).apply(connection);
    }

    @SneakyThrows
    @Override public Document execute(URL url) {
        return this.process(HttpConnection.connect(url)).execute().parse();
    }
}

这只是对实际实现的简化,只关注问题的必要部分,这可以通过尝试使用JsoupHttpService和方法链接来看到:

代码语言:javascript
复制
public Document doSomething() {
    return new JsoupHttpService(){}
        .registerTransformation(connection -> connection.method(Connection.Method.GET))
        .registerTransformation(connection -> connection.userAgent("fake user-agent"))
        .execute("https://www.google.com")
        .parse();
}

如果您在IDE中尝试这样做,它会说一些无法解决方法“execute”的“Transformable”.所以我想知道你们是否知道我如何在不修改两个接口的情况下解决这个问题。我唯一的选择是创建另一个接口,扩展HttpService并尝试调整它内Transformable中定义的方法吗?

EN

回答 2

Stack Overflow用户

发布于 2021-01-08 21:43:31

问题是registerTransformation返回一个TransformableTransformable不是HttpService

你可以通过这样做来实现你想要的:

代码语言:javascript
复制
JsoupHttpService service = new JsoupHttpService();
service.registerTransformation(connection -> connection.method(Connection.Method.GET));
service.registerTransformation(connection -> connection.userAgent("fake user-agent"));
service.execute();

似乎可转换接口的作者没有正确理解何时使用extends是合适的。对(R)的未检查转换应该是这方面的一个线索。

票数 0
EN

Stack Overflow用户

发布于 2021-01-09 01:58:51

我认为几乎任何使用多重继承,即使是接口,都是个坏主意。同时,将泛型和类型的继承混合在一起会导致噩梦般的混乱--看看围绕着ComparableEnum的奇怪结构。

显然这不会阻止我修改代码。

如果有一个仅用于返回类型的类型参数的方法,则该方法的选项是:返回null、抛出异常、执行堆类型污染、不麻烦返回或更糟。

此类构造器问题的解决方案是使用递归定义的类型参数对构建器类型进行混乱的参数化,并可能添加一个抽象的"get this“方法(如果Transformable是抽象的,并且可以有字段,则更常见)。

代码语言:javascript
复制
public interface Transformable<THIS extends Transformable<THIS, T>, T> {
    THIS registerTransformation(Function<T, T> transformation);
    T process(T entity);
}

public class JsoupHttpService implements HttpService<Document>, Transformable<Connection> {
    private final List<Function<Connection, Connection>> fns = new LinkedList<>();

    @Override public JsoupHttpService registerTransformation(Function<Connection, Connection> transformation) {
        this.fns.add(transformation);
        return this;
    }

对于"get this“,假设Transformable有一个常见的默认实现方法

代码语言:javascript
复制
    // Silly example.
    default THIS setSomethingWhichUsuallyHasNoEffect() {
        // In an abstract class, could assign fields here.
        return getThis(); // Cannot inline within source.
    }
    abstract THIS getThis(); // Would be protects in abstract class.

然后在JsoupHttpService

代码语言:javascript
复制
    @Override public JsoupHttpService getThis() {
        return this;
    }
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65636591

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档