gpt4 book ai didi

java - 是否存在推断协方差

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:32:50 24 4
gpt4 key购买 nike

我正在将一些代码重构为构建器模式,并在为子类对构建器进行子类化时遇到问题。

当我有一个构建器子类时,我尝试在父类中链接一个方法,它返回父构建器,所以我的实例不再能够访问子类方法。

public class App {

public static void main(String[] args) {
Parent p;
p = new App().new ChildBuilder()
.withName("Test")
.withNickName("Test1")
.build();// Doesn't Compile
p = new App().new ChildBuilder()
.withNickName("Test1")
.withName("Test")
.build();

}

class Parent {
public Parent(ParentBuilder builder) {}
}

class Child extends Parent {
public Child(ChildBuilder builder) { super(builder); }
}

class ParentBuilder {
private String name;
public ParentBuilder() {}

public Parent build() { return new Parent(this); }

public ParentBuilder withName(String name) {
this.name = name;
return this;
}
}

class ChildBuilder extends ParentBuilder {
private String nickName;
public ChildBuilder withNickName(String nickName) {
this.nickName = nickName;
return this;
}
}
}

main 方法中的第二行不会编译,因为 withName("Test") 在 ParentBuilder 类上并返回一个 ParentBuilder。重新排序链以调用所有 ChildBuilder 方法首先解决了问题,但对于使用我的 api 的人(包括我自己)来说,这听起来像是一种糟糕的体验。
如果我在 child 中添加覆盖,我可以通过协方差使其工作:

        @Override
public ChildBuilder withName(String name) {
super.withName(name);
return this;
}

但这是很多我不想维护的样板代码(每个父构建器可能有一些子类,所以我需要为父类中的每个方法重写每个子类中的这些方法)。

有没有办法在没有覆盖的情况下完成我想做的事情? Java 可以“推断” child 中的协变方法吗?

我也担心这个问题表明我设计的构建器不正确。

最佳答案

不,没有推断协方差,但它被奇怪的重复出现的模板模式(或起源于 C++ 的 CRTP)模仿。

可以通过添加2个使用CRTP(即参数类型为子类)的(包私有(private))抽象类来解决。构建器功能被移至这些类,然后您创建 2 个空类来扩展抽象构建器。

我还更改了构造函数,使其不直接依赖于构建器,而是依赖于实际参数,因为这通常是这样做的,并且它使这里的实现更清晰:

public static void main(String[] args) {
// Both examples now compile
Parent p;
p = new App().new ChildBuilder()
.withName("Test")
.withNickName("Test1")
.build();
p = new App().new ChildBuilder()
.withNickName("Test1")
.withName("Test")
.build();

}

class Parent {
public Parent(String name) {}
}

class Child extends Parent {
public Child(String name, String nickName) { super(name); }
}

abstract class AbstractParentBuilder<T extends AbstractParentBuilder<T>> {
protected String name;
protected AbstractParentBuilder() {}

public Parent build() { return new Parent(name); }

@SuppressWarnings("unchecked")
public T withName(String name) {
this.name = name;
return (T) this;
}
}

class ParentBuilder extends AbstractParentBuilder<ParentBuilder> {}

abstract class AbstractChildBuilder<T extends AbstractChildBuilder<T>> extends AbstractParentBuilder<T> {
protected String nickName;
protected AbstractChildBuilder() {}

public Child build() { return new Child(name, nickName); }

@SuppressWarnings("unchecked")
public T withNickName(String nickName) {
this.nickName = nickName;
return (T) this;
}
}

class ChildBuilder extends AbstractChildBuilder<ChildBuilder> {}

关于java - 是否存在推断协方差,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50426351/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com