Java结合流式接口与策略模式时如何让父类方法返回子类实例
问题根因
当前抽象父类Foo仅声明了数据类型的泛型参数,没有将子类自身的类型纳入泛型约束,导致父类中定义的方法只能固定返回Foo<T>类型,子类调用完父类方法后会丢失自身类型,无法继续调用子类自定义的方法。
改造方案
通过给父类增加自限定的子类泛型参数即可解决,具体修改步骤如下:
步骤1:改造抽象父类Foo
新增泛型参数S指代实际子类类型,修改方法返回值为S:
// 新增S泛型,约束为继承自Foo<T, S>,指向实际实现类 public abstract class Foo<T extends BarData, S extends Foo<T, S>> { T data; public Foo(T data) { this.data = data; } // 修正方法签名缺的括号,返回值改为S public S fooMethod() { // 原有业务逻辑 return (S) this; } }
此处的强转是安全的,泛型约束已经保证了this必然是S类型的实例。
步骤2:修改子类继承逻辑
子类继承Foo时,将自身作为泛型参数S传入:
public class Bar extends Foo<BarData, Bar> { public Bar(BarData data) { super(data); } public Bar barMethod() { // 原有业务逻辑 return this; } }
步骤3:对齐接口与实现类定义
修正原代码中接口名不一致、方法修饰符缺失的问题:
// 统一接口名,泛型对齐父类定义 public interface FluentInterface<T extends BarData, S extends Foo<T, S>> { S initialize(); } // 实现类对齐接口名,补充方法public修饰符 public class BasicFluentInterfaceImplementation implements FluentInterface<BarData, Bar> { @Override public Bar initialize() { // 原有准备数据逻辑 BarData data = new BarData(); return new Bar(data); } }
步骤4:修正调用代码
不要使用原始类型的FluentInterface,否则会丢失泛型信息:
public class Main { public static void main(String[] str) { // 明确指定泛型参数,避免类型擦除 FluentInterface<BarData, Bar> api = new BasicFluentInterfaceImplementation(); // 链式调用全程保留Bar类型,可正常调用所有方法 api.initialize() .fooMethod() .barMethod(); } }
补充说明
该方案是Java实现流式接口的通用写法,后续新增任意Foo的子类,只要继承时将自身作为泛型参数传入,即可直接复用父类的流式调用能力,无需修改父类逻辑。
内容的提问来源于stack exchange,提问作者Toniotti
相关产品推荐
相关产品推荐

