我有三个班级
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()
(它是 Shark.Sbuilder )的方法。
这可以通过将 _Builder 变成泛型来解决,如the answer to this question
中所示这个答案适用于扩展一个孩子,但我遇到的问题不仅限于孙子建设者。
所以这里是构建器的类签名,因为我有它们
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>>{...}
不幸的是,这给了我编译错误。
类型参数'B'不在其范围内;应该延长 '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()
之后,返回的类型(由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
解决方案有效。经过一番蹒跚学步后,我意识到我的getBuilder()方法遇到了第二个问题,导致了进一步的问题。当我回到家时,我将编辑上面的内容以反映正确的功能和解决方案。
最终修改
getBuilder
函数应该是
public static HBuilder<? extends HBuilder<?>> getBuilder(){
return new HBuilder<>();
}
答案 0 :(得分:1)
那么,您的Animal
类具有以下构建器类:
public static class ABuilder<B extends ABuilder<B>> { ... }
类型参数B
的目的是将ABuilder
的任何子类型绑定到此类型变量。但是你不能在子类中正确使用这种子类型绑定。
只需将您的鲨鱼生成器和锤头生成器更改为:
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>
以外的任何内容。