zoukankan      html  css  js  c++  java
  • 【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 }
    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 类的对象调用父类的方法后,返回的是父类对象。

    如下图,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 }
    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类中属性个数较多,重复的属性也较多的情况,可以考虑使用继承。

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

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

    所以,那就这样吧~~~~~~

  • 相关阅读:
    为同一个元素绑定多个不同的事件,并指向相同的事件处理函数方法
    js获取/设置任意元素中间内容的兼容方法
    js元素事件绑定与解绑兼容代码
    js元素事件的绑定与解绑,绑定事件的区别
    【TFS 2017 CI/CD系列
    【TFS 2017 CI/CD系列
    【TFS 2017 CI/CD系列
    【OPPO主题制作系列
    【SQL Server 学习系列】-- ConnectionTimeout、CommandTimeout和BulkCopyTimeout
    【.Net 学习系列】-- Windows身份模拟(WindowsIdentity.Impersonate)时读取Access数据库
  • 原文地址:https://www.cnblogs.com/quiet-snowy-day/p/6091233.html
Copyright © 2011-2022 走看看