美文网首页
小记-父类属性链式赋值

小记-父类属性链式赋值

作者: pq217 | 来源:发表于2022-06-17 13:23 被阅读0次

链式编程

假如当前有个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);
}

相关文章

  • 小记-父类属性链式赋值

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

  • 通过反射给没有 setter 方法的属性赋值,包括父类属性

    需求 在 Junit 中,有时需要为子类继承自父类的属性赋值,但是父类中的属性没有提供 setter 方法,此时可...

  • java 静态 new 对象

    一般情况下: Java中赋值顺序:父类的静态变量赋值自身的静态变量赋值父类成员变量赋值和父类块赋值父类构造函数赋值...

  • iOS子类属性替换父类属性

    父类扩展类中声明了属性A。子类在扩展类中声明了属性B。且A,B同名。先在子类中self.B初始化赋值。则在父类中的...

  • 继承

    原型链式继承 优点:父类新增原型属性和方法,子类都能访问缺点:无法实现多继承;创建子类实例,无法向父类传参;来自原...

  • Spring的继承

    实现Spring的内部继承有两种方法: 1、在父类中进行赋值,子类通过parent属性继承父类的内容 2、因为Ja...

  • 9.3.1- 2 继承

    创建子类的实例时,Python首先需要完成的任务是给父类的所有属性赋值。为此,子类的方法__init__()需要父...

  • JS继承

    1:原型继承 为了让子类继承父类的属性(也包括方法),首先需要定义一个构造函数。然后,将父类的新实例赋值给构造函数...

  • 2.3 KVC设计模式(给对象的属性赋值)

    KVC设计模式(给对象的属性赋值) dog类 App类 Person类 KVC设计模式(给对象的属性赋值.png

  • 16、子类和父类的赋值引用关系

    1、将子类的对象赋值给父类的引用✅。即:父类的引用可以指向子类的对象 2、将父类的对象直接赋值值给子类的引用 ❌,...

网友评论

      本文标题:小记-父类属性链式赋值

      本文链接:https://www.haomeiwen.com/subject/ynacvrtx.html