【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類中屬性個數較多,重複的屬性也較多的狀況,能夠考慮使用繼承。

另外就是一些屬性的設置過程須要對外隱藏,或者須要對外使用統一的對象類型,這時能夠考慮使用繼承。

就本次項目而言,類的屬性值並無那麼多,我的認爲不須要搞那麼複雜。可是領導說「對外要使用統一的對象類型」,上層設計又不讓我插手。

因此,那就這樣吧~~~~~~

相關文章
相關標籤/搜索