Java:在超类方法签名中返回子类
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10968557/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java: returning subclass in superclass method signature
提问by downer
I'm working on a problem where there are several implementations of Foo
, accompanied by several FooBuilder
's. While Foo
's share several common variables that need to be set, they also have distinct variables that require their respective FooBuilder
to implement some specific functionality. For succinctness, I'd like to have the FooBuilder
's setters to use method chaining, like:
我正在解决一个问题,其中有几个 的实现Foo
,并伴随着几个FooBuilder
。虽然Foo
's 共享几个需要设置的公共变量,但它们也有不同的变量,需要各自FooBuilder
实现一些特定的功能。为了简洁起见,我想让FooBuilder
's setter 使用方法链接,例如:
public abstract class FooBuilder {
...
public FooBuilder setA(int A) {
this.A = A;
return this;
}
...
}
and
和
public class FooImplBuilder extends FooBuilder{
...
public FooImplBuilder setB(int B) {
this.B = B;
return this;
}
public FooImplBuilder setC(int C) {
this.C = C;
return this;
}
...
}
And so on, with several different FooBuilder
implementations. This technically does everything I want, however, this approach is sensitive to the order of methods calls when method chaining is performed. The following has method undefined compile errors:
等等,有几种不同的FooBuilder
实现。这在技术上完成了我想要的一切,但是,当执行方法链接时,这种方法对方法调用的顺序很敏感。以下有方法未定义的编译错误:
someFoo.setA(a).setB(b)...
Requiring that the developer think about the order of method calls in the chain. To avoid this, I'd like to have the setters in FooBuilder
somehow return the actual implementing subclass. However, I'm not sure how to do this. What is the best approach?
要求开发者考虑链中方法调用的顺序。为了避免这种情况,我想让 setter 以FooBuilder
某种方式返回实际的实现子类。但是,我不确定如何执行此操作。最好的方法是什么?
采纳答案by Don Roby
This is a good question and a real problem.
这是一个很好的问题,也是一个真正的问题。
The easiest way to deal with it in Java likely involves the use of generics, as mentioned in Jochen's answer.
在 Java 中处理它的最简单方法可能涉及使用泛型,如 Jochen 的回答中所述。
There's a good discussion of the issue and a reasonable solution in this blog entry on Using Inheritance with Fluent Interfaces, which combines generics with the definition of a getThis()
method overriden in builder subclasses to solve the problem of always returning a builder of the correct class.
这篇关于将继承与 Fluent Interfaces结合使用的博客条目对这个问题和合理的解决方案进行了很好的讨论,它将泛型与getThis()
在构建器子类中重写的方法的定义相结合,以解决始终返回正确类的构建器的问题。
回答by zerobandwidth
Having found this excellent answerI am now sharing it around.
找到了这个很好的答案后,我现在正在分享它。
public class SuperClass<I extends SuperClass>
{
@SuppressWarnings( "unchecked" ) // If you're annoyed by Lint.
public I doStuff( Object withThings )
{
// Do stuff with things.
return (I)this ; // Will always cast to the subclass. Causes the Lint warning.
}
}
public class ImplementationOne
extends SuperClass<ImplementationOne>
{} // doStuff() will return an instance of ImplementationOne
public class ImplementationTwo
extends SuperClass<ImplementationTwo>
{} // doStuff() will return an instance of ImplementationTwo
回答by Jochen
Generics might be the way to go here.
泛型可能是这里的方法。
If you declare setA() something like this (pseudo-code)
如果你声明 setA() 这样的东西(伪代码)
<T> T setA(int a)
the compiler should be able to figure out the real types, and if it doesn't you can give hints in the code like
编译器应该能够找出真正的类型,如果不能,您可以在代码中给出提示,例如
obj.<RealFoo>setA(42)