问题描述
我有这样的课程结构:
Stuff
/ \
Food
|
FastFood Drink
| |
Pizza Juice
/ \ / \
| SicilianPizza | OrangeJuice
| AppleJuice
CaliforniaPizza
我可以使用以下构建器创建比萨饼和果汁对象:
I can create pizza and juice objects using builders like this:
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方法都返回正确的对象:
Every setter method of the builder returns correct object:
我想创建一个接受 FastFood的方法.Builder
对象,并使用它创建 FastFood
对象,该对象会将其传递给另一种方法:
I'd like to create a method that would accept a FastFood.Builder
object and use it to create a FastFood
object that would pass it to another method:
public void makeFat(FastFood fastFood) {...}
但是我不能:setter方法不返回 FastFood
,而是返回其父项:
But I can't: setter methods don't return FastFood
, but rather its parents:
我的仿制药有问题吗?
Is there something wrong with my generics? How could that be accomplished?
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
是泛型类型。
There should be a warning saying that FastFood.Builder
is a generic type.
参数类型必须适当地设为泛型。
The parameter type needs to be made appropriately generic. A wildcard will do (constraints will be inferred).
public FastFood testFood(FastFood.Builder<?> fastFoodBuilder) {
这篇关于Java Builder类的泛型层次结构:如何使build()返回正确的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!