gpt4 book ai didi

Java:构建器、继承、泛型 Redux

转载 作者:行者123 更新时间:2023-11-30 06:14:40 25 4
gpt4 key购买 nike

我需要创建一组通过多级层次结构继承的构建器类,其中构建器需要驻留在要构建的类之外以及不同的包中。

从此示例中走出:https://onelostlogician.wordpress.com/2016/10/10/inheritance-generics-and-builders/下面的代码是通过根据要求进行更改而创建的:1. 将构建器移动到顶层,2. 将构建器和待构建放在不同的包中,并向后者添加 setter ,3. 将静态 newXYZ() 方法移动到构建器并删除其类型参数以消除删除冲突。这将是所需产品的合适模型。

package other;

public abstract class BaseClass {
protected Integer field1;

BaseClass () {
}

public Integer getField1 () {
return field1;
}

public void setField1 (Integer field1) {
this.field1 = field1;
}
}

package my;

import other.BaseClass;

public abstract class BaseClassBuilder<T extends BaseClass, BU extends BaseClassBuilder> {
protected T obj;

protected BaseClassBuilder (T obj) {
this.obj = obj;
}

protected final BU getThis () {
return (BU) this;
}

public BU withField1 (Integer field1) {
obj.setField1(field1);
return getThis();
}

public T build () {
return this.obj;
}
}

package other;

import java.util.UUID;

public class SubClass extends BaseClass {
protected UUID field2 = null;

public SubClass () {
}

public UUID getField2 () {
return field2;
}

public void setField2 (UUID field2) {
this.field2 = field2;
}
}

package my;

import java.util.UUID;

import other.SubClass;

public class SubClassBuilder<T extends SubClass, BU extends SubClassBuilder> extends BaseClassBuilder<T, BU> {
protected SubClassBuilder (T obj) {
super(obj);
}

public BU withField2 (UUID field2) {
obj.setField2(field2);
return getThis();
}

public T build () {
return this.obj;
}

public static SubClassBuilder neu () {
return new SubClassBuilder<>(new SubClass());
}
}

package other;

public class SubSubClass extends SubClass {
protected String field3 = null;

public SubSubClass () {
}

public String getField3 () {
return field3;
}

public void setField3 (String field3) {
this.field3 = field3;
}
}

package my;

import other.SubSubClass;

public class SubSubClassBuilder<T extends SubSubClass, BU extends SubSubClassBuilder<T, BU>> extends SubClassBuilder<T, BU> {
protected SubSubClassBuilder (T obj) {
super(obj);
}

public BU withField3 (String field3) {
obj.setField3(field3);
return getThis();
}

public T build () {
return this.obj;
}

public static SubSubClassBuilder neu () {
return new SubSubClassBuilder<>(new SubSubClass());
}
}

结果:SubSubClassBuilder.neu().withField1(..) 返回一个 BaseClassBuilder,withField2(..) 返回一个 SubClassBuilder,如 Android Studio 3.0.1 中的代码完成所示。在每个构建器中重写 getThis() 也不起作用。

回到第一点,我错过了什么?

编辑:遵循 Java: builder pattern, inheritance and generics 的提示它也尝试过像这样的静态(内部)构建器类,但效果相同:

    package my;

import java.util.UUID;

import other.BaseClass;
import other.SubClass;
import other.SubSubClass;

public class Builders {

private Builders () {}

abstract static class BaseClassBuilder<T extends BaseClass, BU extends BaseClassBuilder> {
protected T obj;

protected BaseClassBuilder (T obj) {
this.obj = obj;
}

protected final BU getThis () {
return (BU) this;
}

public BU withField1 (Integer field1) {
obj.setField1(field1);
return getThis();
}

public T build () {
return this.obj;
}
}

public static class SubClassBuilder<T extends SubClass, BU extends SubClassBuilder> extends BaseClassBuilder<T, BU> {
protected SubClassBuilder (T obj) {
super(obj);
}

public BU withField2 (UUID field2) {
obj.setField2(field2);
return getThis();
}

public T build () {
return this.obj;
}

public static SubClassBuilder neu () {
return new SubClassBuilder<>(new SubClass());
}
}

public static class SubSubClassBuilder<T extends SubSubClass, BU extends SubSubClassBuilder<T, BU>> extends SubClassBuilder<T, BU> {
protected SubSubClassBuilder (T obj) {
super(obj);
}

public BU withField3 (String field3) {
obj.setField3(field3);
return getThis();
}

public T build () {
return this.obj;
}

public static SubSubClassBuilder neu () {
return new SubSubClassBuilder<>(new SubSubClass());
}
}
}

最佳答案

好消息:这是可以做到的。使您的方法变得不可能的是您希望中间构建器子类既具体化它们自己的自身类型,又通过子类化保持其开放以进行扩展。事实证明这是不可能的。

为了使其工作,您必须在每个级别都有一个抽象子类,它添加必要的方法并允许进一步扩展子类型,以及一个将自身指定为特定构建器的具体子类。

Class Diagram

这是我改编的实现:

首先,从基类开始。我所做的更改主要是在构造函数中传递 self 类型的类。

portected abstract class BaseClassBuilder<T extends BaseClass, BU extends BaseClassBuilder<T, BU>> {
protected T obj;
private BU self;

protected BaseClassBuilder (T obj, Class<?> selfType) {
this.obj = obj;
this.self = (BU) selfType.cast(this);
}

final BU getThis () {
return self;
}

public BU withField1 (Integer field1) {
obj.setField1(field1);
return getThis();
}

public T build () {
return this.obj;
}
}

现在介绍 SubClassBuilder 的抽象版本。这个添加了我们构建 SubClass 实例所需的所有方法,但仍然是抽象的,因此它仍然可以用于扩展。

public abstract class AbstractSubClassBuilder<T extends SubClass, BU extends AbstractSubClassBuilder<T, BU>> extends BaseClassBuilder<T, BU> {

protected AbstractSubClassBuilder(T obj, Class<?> selfType) {
super(obj, selfType);
}

public BU withField2 (UUID field2) {
obj.setField2(field2);
return getThis();
}
}

这使我们能够非常轻松地为 SubClass 实例创建一个具体的构建器类:

public final class SubClassBuilder extends AbstractSubClassBuilder<SubClass, SubClassBuilder> {

private SubClassBuilder(SubClass obj) {
super(obj, SubClassBuilder.class);
}

public static SubClassBuilder neu () {
return new SubClassBuilder(new SubClass());
}
}

下一个级别的工作原理是一样的;一个抽象类来添加额外的构建器方法,并允许进一步扩展,它扩展了 AbstractSubClassBuilder :

public class AbstractSubSubClassBuilder<T extends SubSubClass, BU extends AbstractSubSubClassBuilder<T, BU>> extends AbstractSubClassBuilder<T, BU> {

protected AbstractSubSubClassBuilder (T obj, Class<BU> selfType) {
super(obj, selfType);
}

public BU withField3 (String field3) {
obj.setField3(field3);
return getThis();
}
}

使其具体化,需要另一个类,但现在静态工厂方法不会隐藏其父类中的一个(neu:你是德国人吗?)

public class SubSubClassBuilder extends AbstractSubSubClassBuilder<SubSubClass, SubSubClassBuilder> {

private SubSubClassBuilder(SubSubClass obj) {
super(obj, SubSubClassBuilder.class);
}

public static SubSubClassBuilder neu () {
return new SubSubClassBuilder(new SubSubClass());
}
}

现在构建任一类的实例都非常简单。

SubSubClass subSubClass = SubSubClassBuilder.neu()
.withField2(UUID.randomUUID())
.withField1(5)
.withField3("3")
.build();

SubClass subClass = SubClassBuilder.neu()
.withField1(66)
.withField2(UUID.randomUUID())
.build();

(归功于 AssertJ 我首先看到了这一点)

关于Java:构建器、继承、泛型 Redux,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49488239/

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