在java中,是否可以创建一个流畅的可扩展类层次结构,其中包含可以按任何顺序调用的方法?
是否可以在java中创建一个可扩展的类层次结构,其方法是流畅的,并且可以以任何顺序调用(是的!请参见下面的答案),即使对于现有类,如果方法是fluant,当您无法访问源代码时也是如此强> 我正在改造一个现有的层次结构,并希望使用一个工厂或至少是一个通用的构造函数和(最终)不可变的构建器模式(JBP.14)。设置字段的方法返回在java中,是否可以创建一个流畅的可扩展类层次结构,其中包含可以按任何顺序调用的方法?,java,design-patterns,generics,runtime-error,method-chaining,Java,Design Patterns,Generics,Runtime Error,Method Chaining,是否可以在java中创建一个可扩展的类层次结构,其方法是流畅的,并且可以以任何顺序调用(是的!请参见下面的答案),即使对于现有类,如果方法是fluant,当您无法访问源代码时也是如此 我正在改造一个现有的层次结构,并希望使用一个工厂或至少是一个通用的构造函数和(最终)不可变的构建器模式(JBP.14)。设置字段的方法返回void——最好是返回一个通用的T——这样我们就能够进行方法链接(现在它们都调用super) 目标: 1. 避免在每个类中创建静态getFactory()方法。 2. 简单方
void
——最好是返回一个通用的T
——这样我们就能够进行方法链接(现在它们都调用super
)
目标:1. 避免在每个类中创建静态getFactory()方法。
2. 简单方法签名。
3. 创建一个通用的工厂方法,但在编译时会发现问题。
4. 出错时,获取编译时错误,而不是运行时错误。 按照要求,非泛型代码非常简单,但不起作用
public class A {
private String a = null;
protected A setA(String a){
this.a = a;
return this;//<== DESIRE THIS TO BE CHAINABLE
}
protected static A factory(){
return new A();
}
}
公共A类{
私有字符串a=null;
受保护的setA(字符串A){
这个a=a;
回答这个;//答案(令我惊讶和满意)是肯定的。我自己回答了这个问题:
如果方法调用返回有问题的类的实例(请参见下面的chainable),您只需做一点工作就可以做到这一点。如果您可以编辑顶级源代码,我还发现了一种更简单的方法:
在顶级课程(A)中:
受保护的最终TA(T型){
返回类型
}
假设C延伸B,B延伸A
援引:
C=newc();
//任何命令都可以,并且您有编译时安全性和IDE帮助。
c、 setA(“a”).a(c).setB(“b”).a(c).setC(“c”);
示例1和3是使现有类层次结构流畅的方法,并允许在现有类流畅的情况下以任何顺序调用方法(但您无权访问或无法更改源)。WAY2是一个示例,您可以访问源,并希望调用尽可能简单
完整SSCCE:
导入静态java.lang.System.out;
公共类测试仪{
公共静态void main(字符串[]args){
//测试1:
for(intx:newint[]{0,1,2}){
A w=getA(x);
//我同意这是一种肮脏的方式…但你可以做到。
链.a(w.setA(“a1”)).a(w实例f C?((C)w).setC(“c1”):空);
out.println(w);
}
//测试方法2:希望这能得到保罗·贝洛拉的认可
//为了简洁、易用和语法上的方便。
C=新的C();
//以编译时类型安全的任何顺序调用方法!
c、 setA(“a2”).a(c).setB(“b2”).a(c).set(“C2”);
out.println(w);
//示例3,即示例1,但已知顶级类为“C”
//但是您没有访问源的权限,无法将“a”方法添加到
//方法调用不必像示例1那样令人讨厌。
c=新的c();
Chain.a(c.setA(“a3”)).a(c.setB(“b3”)).a(c.setC(“c3”);//不比示例2大多少。
out.println(w);
}
公共静态getA(inta){//工厂方法。
retval;//我不喜欢多次返回。
开关(a){
案例0:retval=newa();中断;
案例1:retval=new B();中断;
默认值:retval=newc();break;
}
返回返回;
}
}
甲级考试
公共A类{
私人字符串a;
受保护的字符串getA(){return a;}
//方式2-在这里您可以访问顶级源类。
受保护的最终T a(T type){return type;}//这太棒了!
受保护的集合A(字符串A){this.A=A;返回this;}//Fluent方法
@凌驾
公共字符串toString(){
返回“A[getA()=”+getA()+“]”;
}
}
B级考试
公共类B扩展了{
私有字符串b;
受保护的字符串getB(){return b;}
受保护的B setB(字符串B){this.B=B;返回this;}//Fluent方法
@凌驾
公共字符串toString(){
返回“B[getA()=”+getA()+”,getB()=“+getB()+”]\n
+super.toString();
}
}
测试等级C
公共类C扩展B{
私有字符串c;
受保护的字符串getC(){return c;}
受保护的C setC(字符串C){this.C=C;返回this;}//Fluent方法
@凌驾
公共字符串toString(){
返回“C[getA()=”+getA()+”,getB()=“+getB()+”,getC()=”
+getC()+“]\n”+super.toString();
}
}
链类
/**
*允许与任何类链接,即使是您没有编写和没有的类
*访问的源代码,只要该类是流畅的。
*@作者Gregory G.Bishopggb667@gmail.com(C)2013年11月5日保留所有权利。
*/
公共最终类链{
公共静态ua(K值){//注意这是静态的
返回新的uz(value);//这样IDE名称就不会令人讨厌了
}
}
Chain的助手类
/**
*实例方法无法从链重写静态方法,
*这就是此类存在的原因(即抑制IDE警告,
*并提供流畅的使用)。
*
*@作者Gregory G.Bishopggb667@gmail.com(C)2013年11月5日保留所有权利。
*/
期末班{
public T a;//因此我们可以从链中的最后一个链接获取返回值。
受保护的T(T){this.a=T}//上面的链需要
公共uA(K值){
返回新的u0(值);
}
}
输出:
A[get(A)=A]
B[get(A)=A,getB()=null]
A[getA()=A]
C[getA()=a,getB()=null,getC()=C]
B[get(A)=A,getB()=null]
A[得到(A)=A]
QED:)
我从未见过有人这样做,我认为这可能是一个新的和潜在的
public class B extends A {
private String b = null;
protected Foo setB(String b){
this.b = b;
return this;//<== DESIRE THIS TO BE CHAINABLE
}
protected static B factory(){
return new B();
}
}
Book b = null;
Publisher p = null;
List books = null;
String id = "Elric of Melnibone";
books = Chain.a(b = findBook(id)).a(b != null ? p = b.getPublisher() : null)
.a(p != null ? p.getPublishedBooks(): null).a;
out.println(books==null ? null : Arrays.toString(books.toArray()));
Book b = null;
Publisher p = null;
List books = null;
String id = "Elric of Melnibone";
b = findBook(id);
Array[] books = null;
if( b != null ) {
p = b.getPublisher();
if(p != null) {
books = p.getPublishedBooks();
}
}
out.println(books==null ? null : Arrays.toString(books.toArray()));
B<B> b = B.factoryB();
b.setA("a").setB("b");
A<A> ba = A.factoryA();
ba.setA("a");
public class A<S extends A> extends Chained<S> {
private String a = null;
protected A() {
}
public S setA(String a) {
this.a = a;
return me();
}
public static A<A> factoryA() {
return new A<A>();
}
}
public class B<S extends B> extends A<S> {
private String b = null;
B() {
}
public S setB(String b) {
this.b = b;
return me();
}
public static B<B> factoryB() {
return new B<B>();
}
}
public abstract class Chained<S extends Chained> {
// class should be extended like:
// ... class A<S extends A> extends Chained<S>
public Chained() {
}
public final S me() {
return (S) this;
}
}
BaseA
+- A
+- BaseB
+- B
public class BaseA<S extends BaseA<?>> {
private String a = null;
protected BaseA() {
}
@SuppressWarnings("unchecked")
public S setA(String a) {
this.a = a;
return (S) this;
}
}
public class A extends BaseA<A> {
public static A factoryA() {
return new A();
}
}
public class BaseB<S extends BaseB<?>> extends BaseA<S> {
private String b = null;
protected BaseB() {
}
@SuppressWarnings("unchecked")
public S setB(String b) {
this.b = b;
return (S) this;
}
}
public class B extends BaseB<B> {
public static B factoryB() {
return new B();
}
}
public class Main {
public static void main(String[] args) {
B.factoryB().setA("").setB("").setB("").setA("").setA("");
}
}