You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让父抽象类Setter返回子类实例?实现链式调用

用泛型解决父类Setter返回类型限制导致的子类链式调用问题

完全可以用泛型实现,不用每个子类都重写父类的Setter方法,下面是具体的改造方案:

改造父类,引入自限定泛型

给抽象父类添加一个自限定泛型参数,让Setter方法返回这个泛型类型,而非父类自身类型。

修改BaseEntity

@MappedSuperclass
public abstract class BaseEntity<Self extends BaseEntity<Self>> implements Serializable {
    private Integer id;

    public Integer getId() {
        return id;
    }

    @SuppressWarnings("unchecked")
    public Self setId(Integer id) {
        this.id = id;
        return (Self) this;
    }
}

这里的Self是自限定泛型,要求它必须继承BaseEntity<Self>,确保类型转换的安全性。添加@SuppressWarnings("unchecked")是因为编译器无法直接验证这个强制转换,但我们通过泛型约束保证了this就是Self类型。

修改NamedEntity

同样给NamedEntity添加自限定泛型,并在继承BaseEntity时传递这个泛型参数:

@MappedSuperclass
public abstract class NamedEntity<Self extends NamedEntity<Self>> extends BaseEntity<Self> {
    private String name;

    public String getName() {
        return name;
    }

    @SuppressWarnings("unchecked")
    public Self setName(String name) {
        this.name = name;
        return (Self) this;
    }
}

这样NamedEntity继承的setId方法也会返回Self类型,而非BaseEntity。

修改Person子类

子类继承时,将泛型参数指定为自身类型Person:

@Entity
public class Person extends NamedEntity<Person> {
    private String address;

    public String getAddress() {
        return address;
    }

    public Person setAddress(String address) {
        this.address = address;
        return this;
    }
}

验证链式调用

现在所有Setter方法都会返回Person类型,链式调用可以正常工作:

public Person build() {
    Person person = new Person()
        .setId(1)          // 返回Person,而非BaseEntity
        .setName("name")    // 返回Person,而非NamedEntity
        .setAddress("foo"); // 返回Person
    return person;
}

这种方案的核心是利用自限定泛型让父类的Setter方法返回子类的实际类型,避免了重复重写Setter的冗余工作,同时保持代码的扩展性——后续新增子类时,只需继承对应抽象类并指定自身为泛型参数即可。

内容的提问来源于stack exchange,提问作者Witek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 09:05:23