我有三门课
abstract class Animal {...}
class Shark extends Animal {...}
class Hammerhead extends Shark {...}
每个类都有一个静态内部 _Builder 类。这些是标准构建器类,但它们相互扩展以允许在实例化时完全配置对象。例如构建器的使用可能类似于
Hammerhead.getBuilder().setColor(color.GREY).setFinSize(1.3f).setHammerSize(.9f).build();
这将返回 Hammerhead
的新实例
最初我遇到了这个问题,上面的方法不起作用,因为例如 setColor()
将返回一个 Animal.ABuilder 我无法随后调用 setFinSize()
on (这是Shark.Sbuilder的一种方法)。
通过将_Builder变成泛型来解决这个问题,如 the answer to this question 中所示。
这个答案对于延长一个 child 来说效果很好,但我遇到的问题超出了孙子建筑商的范围。
这是我拥有的构建器的类签名
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'
此错误针对第三个也是最后一个 B
在 SBuilder 定义中
有办法实现吗?
谢谢!
来源
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()
后返回的类型(由 Intellij IDEA 报告)就是定义该函数的任何类。
每行注释是函数调用返回的类型
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() 方法存在第二个问题,这导致了进一步的问题。当我回家时我会编辑上面的内容以反射(reflect)正确的功能和解决方案。
最终编辑
getBuilder
功能应该是
public static HBuilder<? extends HBuilder<?>> getBuilder(){
return new HBuilder<>();
}
最佳答案
好吧,你的Animal
类具有以下构建器类:
public static class ABuilder<B extends ABuilder<B>> { ... }
类型参数的用途B
是绑定(bind) ABuilder
的任何子类型到这个类型变量。但是您没有在子类中正确使用此子类型绑定(bind)。
只需将您的鲨鱼构建器和锤头构建器更改为:
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>
的内容。 .
关于java - 将 Builder 扩展/子类化到直接子级之外,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36029174/