是否可以向 Java AutoValue 中的集合添加值?
Is it possible to add a value to a collection in Java AutoValue?
我有一个带有 List 属性的 Java AutoValue class。我想让构建器附加到列表而不是必须传递整个构建的列表。
示例:
import com.google.auto.value.AutoValue;
@AutoValue
public abstract class Deck {
public abstract List<Card> cards();
public static Builder builder() {
return new AutoValue_Card.Builder()
.cards(new ArrayList<Card>());
}
@AutoValue.Builder
public abstract static class Builder {
public abstract Builder cards(List<Card> cards);
/**
* Append card to cards in the constructed Deck.
*/
public Builder addCard(Card card) {
// Is it possible to write this function?
}
}
}
编写 addCard 函数的最佳解决方案是什么? AutoValue 是否已经以某种方式支持这一点?构建器 class 中的中间卡 属性 对生成器不可见,因此我无法直接访问它。我可以通过在生成器中保留我自己的卡片副本来尝试直接绕过生成器,这是这里唯一的选择吗?
AutoValue 有一些在您使用 Guava 时发挥作用的特殊功能 immutable collections,因为这些集合都有自己的关联构建器类型。 (当然,您当然希望值 类 的属性是不可变的!)
一个功能是您可以定义一个抽象 cardsBuilder()
方法,该方法将启动一个新的适当集合类型的构建器并将其 return 提供给调用者。这是超级灵活的,但令人遗憾的是它 "breaks the chain"。呼叫者现在正在呼叫 ImmutableList.Builder
,无法返回 Deck.Builder
呼叫 build
。
但是你可以通过添加你自己的 addCard
方法来解决这个问题,正如你在上面展示的那样,只需实现它来调用 cardsBuilder().add(card)
然后 return this
而不是生成器。问题已解决!
我相信所有这些都应该在 1.1 中起作用,但如果您遇到问题,请告诉我们!
P.S。抱歉 - 我们有很多关于 AutoValue 用户指南的新 material,包括这个主题,由于一些技术困难,这些内容被推迟到 public 网站。
万一有人觉得它有用 - 这是我假设 Kevin 建议的实际代码。当我第一次偶然发现他的回复时,这并不明显,所以给你:
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
@AutoValue
public abstract class Hand {
public static Builder builder() {
return new AutoValue_Hand.Builder();
}
public abstract Builder toBuilder();
public abstract String name();
public abstract ImmutableList<String> cards();
@AutoValue.Builder
public static abstract class Builder {
public abstract Builder name(String name);
protected abstract ImmutableList.Builder<String> cardsBuilder();
public Builder addCard(String card) {
cardsBuilder().add(card);
return this;
}
public abstract Hand build();
}
}
用法:
Hand fullHouseHand = Hand.builder()
.name("Full House")
.addCard("King")
.addCard("King")
.addCard("King")
.addCard("10")
.addCard("10")
.build();
System.out.print(fullHouseHand);
输出:
Hand{name=Full House, cards=[King, King, King, 10, 10]}
我有一个带有 List 属性的 Java AutoValue class。我想让构建器附加到列表而不是必须传递整个构建的列表。
示例:
import com.google.auto.value.AutoValue;
@AutoValue
public abstract class Deck {
public abstract List<Card> cards();
public static Builder builder() {
return new AutoValue_Card.Builder()
.cards(new ArrayList<Card>());
}
@AutoValue.Builder
public abstract static class Builder {
public abstract Builder cards(List<Card> cards);
/**
* Append card to cards in the constructed Deck.
*/
public Builder addCard(Card card) {
// Is it possible to write this function?
}
}
}
编写 addCard 函数的最佳解决方案是什么? AutoValue 是否已经以某种方式支持这一点?构建器 class 中的中间卡 属性 对生成器不可见,因此我无法直接访问它。我可以通过在生成器中保留我自己的卡片副本来尝试直接绕过生成器,这是这里唯一的选择吗?
AutoValue 有一些在您使用 Guava 时发挥作用的特殊功能 immutable collections,因为这些集合都有自己的关联构建器类型。 (当然,您当然希望值 类 的属性是不可变的!)
一个功能是您可以定义一个抽象 cardsBuilder()
方法,该方法将启动一个新的适当集合类型的构建器并将其 return 提供给调用者。这是超级灵活的,但令人遗憾的是它 "breaks the chain"。呼叫者现在正在呼叫 ImmutableList.Builder
,无法返回 Deck.Builder
呼叫 build
。
但是你可以通过添加你自己的 addCard
方法来解决这个问题,正如你在上面展示的那样,只需实现它来调用 cardsBuilder().add(card)
然后 return this
而不是生成器。问题已解决!
我相信所有这些都应该在 1.1 中起作用,但如果您遇到问题,请告诉我们!
P.S。抱歉 - 我们有很多关于 AutoValue 用户指南的新 material,包括这个主题,由于一些技术困难,这些内容被推迟到 public 网站。
万一有人觉得它有用 - 这是我假设 Kevin 建议的实际代码。当我第一次偶然发现他的回复时,这并不明显,所以给你:
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
@AutoValue
public abstract class Hand {
public static Builder builder() {
return new AutoValue_Hand.Builder();
}
public abstract Builder toBuilder();
public abstract String name();
public abstract ImmutableList<String> cards();
@AutoValue.Builder
public static abstract class Builder {
public abstract Builder name(String name);
protected abstract ImmutableList.Builder<String> cardsBuilder();
public Builder addCard(String card) {
cardsBuilder().add(card);
return this;
}
public abstract Hand build();
}
}
用法:
Hand fullHouseHand = Hand.builder()
.name("Full House")
.addCard("King")
.addCard("King")
.addCard("King")
.addCard("10")
.addCard("10")
.build();
System.out.print(fullHouseHand);
输出:
Hand{name=Full House, cards=[King, King, King, 10, 10]}