Extending/Subclassing 超越直接 child 的构建器
Extending/Subclassing a Builder beyond a direct child
我有三个classes
abstract class Animal {...}
class Shark extends Animal {...}
class Hammerhead extends Shark {...}
每个 classes 都有一个静态内部 _Builder class。这些是标准构建器 classes,但它们相互扩展以允许在实例化时对 object 进行完整配置。例如构建器的使用可能类似于
Hammerhead.getBuilder().setColor(color.GREY).setFinSize(1.3f).setHammerSize(.9f).build();
return Hammerhead
的新实例
最初我有这个问题,上面的方法不起作用,因为例如 setColor()
会 return 一个 Animal.ABuilder 我不能随后调用 setFinSize()
on(这是 Shark.Sbuilder 的方法)。
这已通过将 _Builder 变成泛型来补救,如
中所示
答案对于扩展一个 child 很有效,但我在扩展到一个 grandchild builder 时遇到了问题。
这里是 class 建造者的签名,因为我有
static class ABuilder<B extends ABuilder<B>>{...}
static class SBuilder<B extends SBuilder<B>> extends ABuilder<B extends ABuilder<B>>{...}
static class HBuilder<B extends HBuilder<B>> extends SBuilder<B extends SBuilder<B>>{...}
不幸的是,这给了我编译错误。
Type Parameter 'B' is not within it's bounds; should extend
'Animal.ABuilder'
此错误针对 SBuilder 定义中的第三个也是最后一个 B
有办法实现吗?
谢谢!
来源
Animal.java
package com.example;
public abstract class Animal {
String color;
public Animal(ABuilder builder){
this.color = builder.color;
}
public static class ABuilder<B extends ABuilder<B>> {
String color;
public B setColor(String c){
color = c;
return (B)this;
}
}
}
Shark.java
package com.example;
public class Shark extends Animal {
float fin_size;
public Shark(SBuilder builder){
super(builder);
fin_size = builder.fins;
}
// Problems are in this general area: \/
public static class SBuilder<B extends SBuilder<B>> extends ABuilder<B extends ABuilder<B>>{
float fins;
public B setFinSize(float size){
this.fins = size;
return (B) this;
}
public Shark build(){
return new Shark(this);
}
}
}
Hammerhead.java
package com.example;
public class Hammerhead extends Shark {
float hammer;
public Hammerhead(HBuilder builder) {
super(builder);
hammer = builder.hammer;
}
public static HBuilder<? extends HBuilder> getBuilder(){
return new HBuilder<HBuilder>();
}
public static class HBuilder<B extends HBuilder<B>> extends SBuilder<B extends SBuilder<B>> { {
float hammer;
public B setHammerSize(float hammer) {
this.hammer = hammer;
return (B)this;
}
public Hammerhead build(){
return new Hammerhead(this);
}
}
}
编辑
根据 Seelenvirtuose 的回答:
你的回答对我来说很有意义。我以为我已经解决了问题,但现在我已经进行了更改,它仍然没有按预期工作:
在第一次调用 setColor()
之后,returned 类型(由 Intellij IDEA 报告)就是 class 定义函数的类型。
每一行的注释都是return函数调用
编辑的类型
Hammerhead hh =
Hammerhead.getBuilder() // HBuilder<? extends HBuilder> //
.setColor("Black") // ? extends com.example.Hammerhead.HBuilder
.setHammerSize(10f) // HBuilder
.setFinSize(10f) // SBuilder
.setColor("Fuschia") // ABuilder
.setFinSize(10f) // Error: No such method on ABuilder
.build(); // Also does not work because build()
// should be called on an HBuilder
编辑 2
解决方案有效。经过一番摸索之后,我意识到我的 getBuilder() 方法有第二个问题,这导致了进一步的问题。我会在回家后编辑以上内容以反映正确的功能和解决方案。
最终编辑
getBuilder
函数应该是
public static HBuilder<? extends HBuilder<?>> getBuilder(){
return new HBuilder<>();
}
那么,您的 Animal
class 有以下生成器 class:
public static class ABuilder<B extends ABuilder<B>> { ... }
类型参数B
的目的是将ABuilder
的任何子类型绑定到这个类型变量。但是您没有在 subclasses.
中正确使用此子类型绑定
只需将您的鲨鱼生成器和锤头生成器更改为:
public static class SBuilder<B extends SBuilder<B>> extends ABuilder<B> { ... }
public static class HBuilder<B extends HBuilder<B>> extends SBuilder<B> { ... }
由于 B
已经在扩展 SBuilder
(分别为 HBuilder
),因此无需扩展 ABuilder<B>
。
我有三个classes
abstract class Animal {...}
class Shark extends Animal {...}
class Hammerhead extends Shark {...}
每个 classes 都有一个静态内部 _Builder class。这些是标准构建器 classes,但它们相互扩展以允许在实例化时对 object 进行完整配置。例如构建器的使用可能类似于
Hammerhead.getBuilder().setColor(color.GREY).setFinSize(1.3f).setHammerSize(.9f).build();
return Hammerhead
最初我有这个问题,上面的方法不起作用,因为例如 setColor()
会 return 一个 Animal.ABuilder 我不能随后调用 setFinSize()
on(这是 Shark.Sbuilder 的方法)。
这已通过将 _Builder 变成泛型来补救,如
答案对于扩展一个 child 很有效,但我在扩展到一个 grandchild builder 时遇到了问题。
这里是 class 建造者的签名,因为我有
static class ABuilder<B extends ABuilder<B>>{...}
static class SBuilder<B extends SBuilder<B>> extends ABuilder<B extends ABuilder<B>>{...}
static class HBuilder<B extends HBuilder<B>> extends SBuilder<B extends SBuilder<B>>{...}
不幸的是,这给了我编译错误。
Type Parameter 'B' is not within it's bounds; should extend 'Animal.ABuilder'
此错误针对 SBuilder 定义中的第三个也是最后一个 B
有办法实现吗?
谢谢!
来源
Animal.java
package com.example;
public abstract class Animal {
String color;
public Animal(ABuilder builder){
this.color = builder.color;
}
public static class ABuilder<B extends ABuilder<B>> {
String color;
public B setColor(String c){
color = c;
return (B)this;
}
}
}
Shark.java
package com.example;
public class Shark extends Animal {
float fin_size;
public Shark(SBuilder builder){
super(builder);
fin_size = builder.fins;
}
// Problems are in this general area: \/
public static class SBuilder<B extends SBuilder<B>> extends ABuilder<B extends ABuilder<B>>{
float fins;
public B setFinSize(float size){
this.fins = size;
return (B) this;
}
public Shark build(){
return new Shark(this);
}
}
}
Hammerhead.java
package com.example;
public class Hammerhead extends Shark {
float hammer;
public Hammerhead(HBuilder builder) {
super(builder);
hammer = builder.hammer;
}
public static HBuilder<? extends HBuilder> getBuilder(){
return new HBuilder<HBuilder>();
}
public static class HBuilder<B extends HBuilder<B>> extends SBuilder<B extends SBuilder<B>> { {
float hammer;
public B setHammerSize(float hammer) {
this.hammer = hammer;
return (B)this;
}
public Hammerhead build(){
return new Hammerhead(this);
}
}
}
编辑
根据 Seelenvirtuose 的回答:
你的回答对我来说很有意义。我以为我已经解决了问题,但现在我已经进行了更改,它仍然没有按预期工作:
在第一次调用 setColor()
之后,returned 类型(由 Intellij IDEA 报告)就是 class 定义函数的类型。
每一行的注释都是return函数调用
编辑的类型Hammerhead hh =
Hammerhead.getBuilder() // HBuilder<? extends HBuilder> //
.setColor("Black") // ? extends com.example.Hammerhead.HBuilder
.setHammerSize(10f) // HBuilder
.setFinSize(10f) // SBuilder
.setColor("Fuschia") // ABuilder
.setFinSize(10f) // Error: No such method on ABuilder
.build(); // Also does not work because build()
// should be called on an HBuilder
编辑 2
解决方案有效。经过一番摸索之后,我意识到我的 getBuilder() 方法有第二个问题,这导致了进一步的问题。我会在回家后编辑以上内容以反映正确的功能和解决方案。
最终编辑
getBuilder
函数应该是
public static HBuilder<? extends HBuilder<?>> getBuilder(){
return new HBuilder<>();
}
那么,您的 Animal
class 有以下生成器 class:
public static class ABuilder<B extends ABuilder<B>> { ... }
类型参数B
的目的是将ABuilder
的任何子类型绑定到这个类型变量。但是您没有在 subclasses.
只需将您的鲨鱼生成器和锤头生成器更改为:
public static class SBuilder<B extends SBuilder<B>> extends ABuilder<B> { ... }
public static class HBuilder<B extends HBuilder<B>> extends SBuilder<B> { ... }
由于 B
已经在扩展 SBuilder
(分别为 HBuilder
),因此无需扩展 ABuilder<B>
。