小记-父类属性链式赋值

2022-06-17  本文已影响0人  pq217

链式编程

假如当前有个A类,两个属性name和info(泛型),我们想用链式编程的方式给属性赋值,很简单,只要赋值的方法返回this即可

public class A<T> {

    private String name;

    private T info;

    public A name(String name) {
        this.name = name;
        return this;
    }

    public A info(T info) {
        this.info = info;
        return this;
    }
}

这样就可以用链式的方式构造A对象

A<String> a = new A<String>().name("pq").info("handsome");

抽象类

假如我们现在有多种A,都有name和info属性,此时我们可能会抽象出一个AbstractA,并把name和info属性移到抽象类中

public abstract class AbstractA<T> {

    protected String name;

    protected T info;

    public AbstractA<T> name(String name) {
        this.name = name;
        return this;
    }

    public AbstractA<T> info(T info) {
        this.info = info;
        return this;
    }
    
    public abstract void doSomething();
}

然后用某个A1去继承这个抽象的A

public class A1<T> extends AbstractA<T>{
    @Override
    public void doSomething() {}
}

这时候问题出现了,原链式构造方式报错了

image.png

因为name(String name)返回的是AbstractA而不是它的实现A1,如果A1还有特殊属性也想用链式方式赋值那是链不到一起去的,显然不是想要的效果

解决

一个简单的思路是把name和info的赋值方法写到实现类中,但这样显然不好,明明是父类的属性却要每个子类都写一遍赋值方法,代码十分冗余

还有一种方式就是强转,也能达到效果,但写法太难看:

A1<String> a = (A1) (((A1) = new A1<String().name("pq")).info("handsome"));

回头看看问题本身,出现这个问题的主要原因在于抽象类AbstractA不知道子类是什么类型的,所以解决方案也出来了,可以在子类继承时把子类的类型通过泛型告知抽象类

修改抽象类如下

public abstract class AbstractA<S extends AbstractA<S, T>, T> {

    protected String name;

    protected T info;

    public S name(String name) {
        this.name = name;
        return (S) this;
    }

    public S info(T info) {
        this.info = info;
        return (S) this;
    }

    public abstract void doSomething();
}

通过泛型S传入实现AbstractA的类的类型,赋值返回时强转为S,这时实现类只需要把自己的类型传入即可

public class A<T> extends AbstractA<A<T>, T> {
    @Override
    public void doSomething() {}
}

再次使用就及其丝滑了

A<String> a = new A<String>().name("pq").info("handsome");

总结

利用泛型,可以实现让父类得到子类的类型,这种方式很多场景其实都能用到,比如现在要定义一个可互相冲突的对象接口,就可以如下定义

public interface Conflictable<T extends Conflictable<T>> {
    boolean conflictTo(T to);
}
上一篇 下一篇

猜你喜欢

热点阅读