【Java】子类的链式调用

记录最近在项目设计中遇到的一个小问题。app

前提:有这样两个POJO类,它们均可以经过链式调用的方式来设置其属性值,其中一个类继承了另外一个类。eclipse

问题:经过链式调用,子类对象访问父类方法后,如何使返回对象还是子类对象,仍然能够继续链式调用子类的方法?ide

结论:子类重写父类中须要被调用的方法。在子类重写的方法中,首先经过super关键字调用父类方法,ui

        而后经过return this语句返回子类对象。this

 

为了更具体、更形象的描述问题和解决办法,上示例代码。 spa

BaseOption、AppearanceOption 是两个实现了链式调用的POJO类,其中AppearanceOption 继承自BaseOption。设计

 1 package com.practice.option;
 2 
 3 public class BaseOption {
 4 
 5     private String id;
 6 
 7     private String name;
 8 
 9     public String getId() {
10         return id;
11     }
12 
13     public String getName() {
14         return name;
15     }
16 
17     public BaseOption setId(String id) {
18         this.id = id;
19         return this;
20     }
21 
22     public BaseOption setName(String name) {
23         this.name = name;
24         return this;
25     }
26 
27 }
View Code
 1 package com.practice.option;
 2 
 3 public class AppearanceOption extends BaseOption {
 4 
 5     private String color;
 6 
 7     private String shape;
 8 
 9     private String size;
10 
11     public String getColor() {
12         return color;
13     }
14 
15     public String getShape() {
16         return shape;
17     }
18 
19     public String getSize() {
20         return size;
21     }
22 
23     public AppearanceOption setColor(String color) {
24         this.color = color;
25         return this;
26     }
27 
28     public AppearanceOption setShape(String shape) {
29         this.shape = shape;
30         return this;
31     }
32 
33     public AppearanceOption setSize(String size) {
34         this.size = size;
35         return this;
36     }
37 
38 }
View Code

此时,AppearanceOption 类的对象调用父类的方法后,返回的是父类对象。code

以下图,setId()方法返回的是BaseOption对象,eclipse自动提示中看不到子类的方法。对象

 

修改子类AppearanceOption 的代码,重写父类方法。blog

 1 package com.practice.option;
 2 
 3 public class AppearanceOption extends BaseOption {
 4 
 5     private String color;
 6 
 7     private String shape;
 8 
 9     private String size;
10 
11     public String getColor() {
12         return color;
13     }
14 
15     public String getShape() {
16         return shape;
17     }
18 
19     public String getSize() {
20         return size;
21     }
22 
23     public AppearanceOption setColor(String color) {
24         this.color = color;
25         return this;
26     }
27 
28     public AppearanceOption setShape(String shape) {
29         this.shape = shape;
30         return this;
31     }
32 
33     public AppearanceOption setSize(String size) {
34         this.size = size;
35         return this;
36     }
37     
38     @Override
39     public AppearanceOption setId(String id) {
40         super.setId(id);
41         return this;
42     }
43 
44     @Override
45     public AppearanceOption setName(String name) {
46         super.setName(name);
47         return this;
48     }
49 
50 }
View Code

如今setId()方法返回的是AppearanceOption 对象,eclipse自动提示中能够看到子类的方法了。

从结论来看,并无用到多么高深的技术,主要仍是对面向对象特征的理解和运用。但是,在实际设计代码结构的时候愣是半天没想到。

主要的解决思路是来自Java源码的启发。在Java中,最多见的链式调用就是 StringBuffer、StringBuilder 类中的 append() 方法。咱们能够经过连续的.append().append()方法来完成字符串的拼接。若是稍微熟悉源码,可能会知道 StringBuffer、StringBuilder 这两个类都继承自抽象类AbstractStringBuilder,该抽象类中也有append() 方法。答案显而易见了,查看一下 StringBuffer 或者 StringBuilder 的源码就知道了。

 

 


扩展问题:

1.什么状况下适合采用这种链式的方法调用?

这里使用的所谓链式调用,其实是同一个对象的多个方法的连续调用。也就是说,在这个长链中的每一个方法返回的都是相同的类型,相同的对象。例如,StringBuilder中append方法的连续调用,JSONObject中的accumulate、put等方法也能够连续调用。这些被调用的方法都有“构建”的特性,都是用于完善实例对象。使用链式调用代码容易编写,看起来比较简洁也容易阅读和理解,但也应该注意代码长度,适当换行。

若是被调用的方法返回的类型不一样,则不适合链式调用。由于各方法返回的类型被隐藏了,代码不容易理解,另外在Debug的时候也是比较麻烦的。

 

2.对于项目来讲,采用这种继承结构是否合理?是否设计过分?

对于简单的POJO类来讲,若是类中的属性个数在十几个之内,我以为彻底不必用继承。

若是各POJO类中属性个数较多,重复的属性也较多的状况,能够考虑使用继承。

另外就是一些属性的设置过程须要对外隐藏,或者须要对外使用统一的对象类型,这时能够考虑使用继承。

就本次项目而言,类的属性值并无那么多,我的认为不须要搞那么复杂。可是领导说“对外要使用统一的对象类型”,上层设计又不让我插手。

因此,那就这样吧~~~~~~

相关文章
相关标签/搜索