Java - Inherited Fluent method return type to return incident class' type, not parent's

给你一囗甜甜゛ 提交于 2019-12-19 07:36:11

问题


When you employ a fluent approach you might have the following scenario:

public class Foo<T extends a>{

    public Foo<T> someMethod(){
          System.out.println("foo");
          return this;
    }

}


public class Bar<T extends b> extends Foo<T> {

         public Bar<T> barMethod(){

            System.out.println("bar");
            return this;
         }

}


public class a{}
public class b extends a{}

A strength of a fluent interface is that you can chain method invocations, but whilst Bar has inherited someMethod(), the return type is Foo not Bar which would break the following chain:

new Bar<b>().someMethod().barMethod();

One answer could be to add @Overrides for every inherited method, such that Bar has the additional method:

 @Override
 public Bar<T> someMethod(){
          System.out.println("foo");
          return this;
    }

But in large classes, and extended class hierarchies this can prove a mess of redundancy surely?! Is there an appropriate return type to give to fluent methods whereby every class that inherits it will return an object of its specific type (so that we can chain methods without casts)?

I tried:

        public <U extends Foo<T>> U someMethod(){
          System.out.println("foo");
          return this;
    }

To alas, no avail. I am hoping someone knows of a simple and elegant solution to this problem. The project is large and so it needs to be maintainable and extensible if possible.

Thank you to any help you can provide in this scenario.


回答1:


You can do it like this, if you don't mind an unchecked cast:

public class Foo<T, F extends Foo<T, F>> {
  public F someMethod() {
    System.out.println("foo");
    return (F) this; // <--- That's the unchecked cast! Tucked safely away.
  }
  public static void main(String[] args) {
    new Bar<String>().someMethod().barMethod();
  }
}

class Bar<T> extends Foo<T, Bar<T>> {
  public Bar<T> barMethod() {
    System.out.println("bar");
    return this;
  }
}

Personally, I disable the unchecked cast warning globally for the whole project.




回答2:


What you can do is define barMethod method abstract so now you can call it on the Foo type.

public abstract class Foo<T extends a> {

    public Foo<T> someMethod() {
        System.out.println("foo");
        return this;
    }

    public abstract Foo<T> barMethod();
}

Now you can easily call

new Bar<b>().someMethod().barMethod();


来源:https://stackoverflow.com/questions/13118648/java-inherited-fluent-method-return-type-to-return-incident-class-type-not-p

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!