Java子类的链式调用
Posted 安静的下雪天
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java子类的链式调用相关的知识,希望对你有一定的参考价值。
记录最近在项目设计中遇到的一个小问题。
前提:有这样两个POJO类,它们都可以通过链式调用的方式来设置其属性值,其中一个类继承了另一个类。
问题:通过链式调用,子类对象访问父类方法后,如何使返回对象仍是子类对象,仍然可以继续链式调用子类的方法?
结论:子类重写父类中需要被调用的方法。在子类重写的方法中,首先通过super关键字调用父类方法,
然后通过return this语句返回子类对象。
为了更具体、更形象的描述问题和解决办法,上示例代码。
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 }
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 }
此时,AppearanceOption 类的对象调用父类的方法后,返回的是父类对象。
如下图,setId()方法返回的是BaseOption对象,eclipse自动提示中看不到子类的方法。
修改子类AppearanceOption 的代码,重写父类方法。
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 }
现在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类中属性个数较多,重复的属性也较多的情况,可以考虑使用继承。
另外就是一些属性的设置过程需要对外隐藏,或者需要对外使用统一的对象类型,这时可以考虑使用继承。
就本次项目而言,类的属性值并没有那么多,个人认为不需要搞那么复杂。但是领导说“对外要使用统一的对象类型”,上层设计又不让我插手。
所以,那就这样吧~~~~~~
以上是关于Java子类的链式调用的主要内容,如果未能解决你的问题,请参考以下文章