gpt4 book ai didi

Java 构建器类泛型层次结构 : how to make build() return correct method

转载 作者:行者123 更新时间:2023-12-02 01:14:33 24 4
gpt4 key购买 nike

我有这个类结构:

                Stuff
/ \
Food
|
FastFood Drink
| |
Pizza Juice
/ \ / \
| SicilianPizza | OrangeJuice
| AppleJuice
CaliforniaPizza

我可以使用这样的构建器创建披萨和果汁对象:

CaliforniaPizza californiaPizze = CaliforniaPizza.builder(2)
.addTopping("Tomatoes").addOlives(true).build();
SicilianPizza sicilianPizza = SicilianPizza.builder(1)
.addTopping("Bacon").addCheese(false).build();

AppleJuice appleJuice = AppleJuice.builder(40)
.setPrice(120).setAlcoholVolume(0).setAppleColor("yellow").build();
OrangeJuice orangeJuice = OrangeJuice.builder(35).setOrangeSize(8).build();

构建器的每个 setter 方法都会返回正确的对象:

enter image description here

我想创建一个接受 FastFood.Builder 对象的方法,并使用它来创建一个 FastFood 对象,并将其传递给另一个方法:

public void makeFat(FastFood fastFood)  {...}

但我不能:setter 方法不返回 FastFood,而是返回其父级:

enter image description here

我的泛型有问题吗?怎么可能实现呢?

package pizza;

import java.util.*;

class TestStuff {
public static void main(String[] args) {
CaliforniaPizza californiaPizze = CaliforniaPizza.builder(2)
.addTopping("Tomatoes").addOlives(true).build();
SicilianPizza sicilianPizza = SicilianPizza.builder(1)
.addTopping("Bacon").addCheese(false).build();

AppleJuice appleJuice = AppleJuice.builder(40)
.setPrice(120).setAlcoholVolume(0).setAppleColor("yellow").build();
OrangeJuice orangeJuice = OrangeJuice.builder(35).setOrangeSize(8).build();
}

public FastFood testFood(FastFood.Builder fastFoodBuilder) {
//return fastFoodBuilder.setMealType("fd").addOlives(true).setPrice(20).build();
}

public void makeFat(FastFood fastFood) {}
}



abstract class Stuff {
protected double price;

protected Stuff() {}

protected abstract class Builder<T extends Builder<T>> {
protected abstract Stuff build();
protected abstract T self();

public T setPrice(double price) {
Stuff.this.price = price;
return self();
}
}
}

abstract class Food extends Stuff {
protected String mealType; //breakfast/dinner/etc

protected Food() {}

public abstract class Builder<T extends Builder<T>> extends Stuff.Builder<T> {
protected abstract Food build();
protected abstract T self();

public T setMealType(String mealType) {
Food.this.mealType = mealType;
return self();
}
}
}

abstract class FastFood extends Food {
protected int harm;

protected FastFood() {}

public abstract class Builder<T extends Builder<T>> extends Food.Builder<T> {
protected abstract FastFood build();
protected abstract T self();

public T setHarm(int harm) {
FastFood.this.harm = harm;
return self();
}
}
}

abstract class Pizza extends FastFood {
protected List<String> toppings = new ArrayList<>(); //optional
protected int size; //obligatory

protected Pizza(int size) {this.size = size;}

public abstract class Builder<T extends Builder<T>> extends FastFood.Builder<T> {
public T addTopping(String topping) {
toppings.add(topping);
return self();
}
}
}

class CaliforniaPizza extends Pizza {
private boolean addOlives;

private CaliforniaPizza(int size) {super(size);}

public static Builder builder(int size) {return new CaliforniaPizza(size).new Builder();}

public class Builder extends Pizza.Builder<Builder> {
@Override
public CaliforniaPizza build() {
return CaliforniaPizza.this;
}

@Override
public Builder self() {return this;}

public Builder addOlives(boolean addOlives) {
CaliforniaPizza.this.addOlives = addOlives;
return this;
}
}
}

class SicilianPizza extends Pizza {
private boolean addCheese;

private SicilianPizza(int size) {super(size);}

public static Builder builder(int size) {
return new SicilianPizza(size).new Builder();
}

public class Builder extends Pizza.Builder<Builder> {
@Override
public SicilianPizza build() {return SicilianPizza.this;}

@Override
public Builder self() {return this;}

public Builder addCheese(boolean addCheese) {
SicilianPizza.this.addCheese = addCheese;
return this;
}
}
}

abstract class Drink extends Stuff {
protected double density;
protected double alcoholVolume;

protected Drink(double density) {this.density = density;}

public abstract class Builder<T extends Builder<T>> extends Stuff.Builder<T> {
protected abstract Drink build();
protected abstract T self();

public T setAlcoholVolume(double alcoholVolume) {
Drink.this.alcoholVolume = alcoholVolume;
return self();
}
}
}

abstract class Juice extends Drink {
private String color;

protected Juice(double density) {super(density);}

public abstract class Builder<T extends Builder<T>> extends Drink.Builder<T> {
public Builder<T> setColor(String color) {
Juice.this.color = color;
return self();
}
}
}
class AppleJuice extends Juice {
private String appleColor;

private AppleJuice(double density) {super(density);}

public static Builder builder(double density) {return new AppleJuice(density).new Builder();}

public class Builder extends Juice.Builder<Builder> {
@Override
public AppleJuice build() {
return AppleJuice.this;
}

@Override
public Builder self() {
return this;
}

public Builder setAppleColor(String appleColor) {
AppleJuice.this.appleColor = appleColor;
return this;
}
}
}

class OrangeJuice extends Juice{
private int orangeSize;

private OrangeJuice(double density) {super(density);}

public static Builder builder(double density) {return new OrangeJuice(density).new Builder();}

public class Builder extends Juice.Builder<Builder> {
@Override
public OrangeJuice build() {return OrangeJuice.this;}

@Override
public Builder self() {return this;}

public Builder setOrangeSize(int orangeSize) {
OrangeJuice.this.orangeSize = orangeSize;
return this;
}
}
}

最佳答案

你有一行:

public FastFood testFood(FastFood.Builder fastFoodBuilder) {

而且:

abstract class FastFood extends Food  {
...
public abstract class Builder<T extends Builder<T>> extends Food.Builder<T> {

应该有一个警告,指出 FastFood.Builder 是泛型类型。

参数类型需要适本地通用。通配符即可(将推断约束)。

public FastFood testFood(FastFood.Builder<?> fastFoodBuilder) {

关于Java 构建器类泛型层次结构 : how to make build() return correct method,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58883563/

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