• 第14条:在公有类中使用访问方法而非公有域


    有时候、可能会编写一些退化类(degenerate classes),没有什么作用,只是用来集中实例域:

    1 class Point {
    2     public double x;
    3     public double y;
    4 }

    由于这种类的数据是可以直接被访问的,这些类没有提供封装(encapsulation)的功能。如果不改变API,就无法改变它的数据表示法,也无法强加任何约束条件,当域被访问时,也无法采取任何辅助的行动。对于这种可变的类来说,应该用包含私有域和公有设值方法(setter)的类来代替:

     1 class Point {
     2     private double x;
     3     private double y;
     4     public Point(double x, double y) {
     5         super();
     6         this.x = x;
     7         this.y = y;
     8     }
     9     public double getX() {
    10         return x;
    11     }
    12     public void setX(double x) {
    13         this.x = x;
    14     }
    15     public double getY() {
    16         return y;
    17     }
    18     public void setY(double y) {
    19         this.y = y;
    20     }
    21 }

    毫无疑问,说到公有类的时候,坚持面向对象程序设计思想的看法是正确的:如果类可以在它所在的包的外部进行访问,就提供访问方法,以保留将来改变该类的内部表示法的灵活性。如果类暴露了它的数据域,要想将来改变其内部表示法是不可能的,因为公有类的客户端代码已经遍布各处了。

    然而,如果类是包级私有的,或者是私有的嵌套类,直接暴露它的数据域并没有本质的错误。虽然客户端代码与该类的内部表示法紧密相连,但是这些代码被限定在包含该类的包中,如果有必要,不改变包之外的任何代码而只改变内部数据表示法也是可以的。在私有嵌套类的情况下,改变的作用范围被进一步限制在外围类中。

    让公有类直接暴露域从来不是种好的办法,但是如果域是不可改变的,这种做法的危害就比较小一些。如果不改变类的API,就无法改变这种类的表示法,当域被读取的时候,你也无法采取任何辅助的行为,但是可以强加约束条件,例如,这种类确保了每个实例都表示一个有效的时间:

     1 public final class Time {
     2     private static final int HOUR_PER_DAY = 24;
     3     private static final int MINUTES_PER_HOUR = 60;
     4     
     5     public final int hour;
     6     public final int minute;
     7     
     8     public Time(int hour, int minute) {
     9         if(hour < 0 || hour >= HOUR_PER_DAY)
    10             throw new IllegalArgumentException("Hour:" + hour);
    11         if(minute < 0 || minute >= MINUTES_PER_HOUR)
    12             throw new IllegalArgumentException("Min:" + minute);
    13         this.hour = hour;
    14         this.minute = minute;
    15     }
    16 }

    总之,公有类永远都不应该暴露在可变的域。虽然还是有问题,但是让公有类暴露不可变域其危害比较小。但是,有时候会需要包级私有的或者私有的嵌套类来暴露域,无论这个类是可变的还是不可变的。

  • 相关阅读:
    MySQL LIMIT OFFSET
    Sublime Text 3安装清爽主题(著名的Soda Theme)
    MySQL无法远程连接解决方案
    算法题:李嘉诚保险柜密码问题
    一些不错的算法学习练习站点
    [转]MySQL远程连接ERROR 2003 (HY000):Can't connect to MySQL server on'XXXXX'(111) 的问题
    使用什么工具连接MySQL Server
    CentOS 7修改MySQL 5.6字符集为UTF-8
    CentOS 7 Minimal编译安装MySQL5.6
    如何使浏览器默认下载文件而不是打开文件
  • 原文地址:https://www.cnblogs.com/remote/p/10193095.html
Copyright © 2020-2023  润新知