第16项: 在公有类中使用访问方法而非公有域

本文讨论了面向对象设计原则中关于公有类使用访问方法而非直接暴露字段的重要性。对于可变类,提供私有字段和公共访问方法以保留内部表示法的灵活性。公共类直接暴露字段会导致未来更改困难,而包级私有或私有嵌套类直接暴露字段的影响相对较小,尤其是在不变类情况下。Java平台库中的某些类如Point和Dimension作为反面例子,强调了遵循这一原则的必要性。
摘要由CSDN通过智能技术生成

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

// Degenerate classes like this should not be public!
class Point {
    public double x;
    public double y;
}

  由于这种类的数据域是可以被直接访问的,这些类没有提供封装(encapsulation)(第15项)。如果不改变API,就无法改变他的数据表示法,也无法强加任何约束条件;当字段被访问的时候,无法采取任何辅助的行为。坚持面向对象程序设计的程序猿面对这种类深恶痛绝,认为应该用包含私有字段和公共访问方法(getters)的类代替。对于可变的类来说,应该用包含私有字段和公有设置方法(setters)的类代替:

// Encapsulation of data by accessor methods and mutators
class Point {
    private double x;
    private double y;
    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }
    public double getX() { return x; }
    public double getY() { return y; }
    public void setX(double x) { this.x = x; }
    public void setY(double y) { this.y = y; }
}

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

  然而,一个类是包级私有的,或者是私有的嵌套类,直接暴露它的数据字段并没有本质的错误 ———— 假设这些数据字段确实描述了该类所提供的抽象。这种方法比访问方法的做法更不会产生视觉混乱,虽然客户端代码与该类的内部表示法紧密相连,但是这些代码被限定在包含该类的包中。如果有必要更改表示法,你可以在不触及包外的任何代码的情况加进行更改。对于私有嵌套类,更改的范围进一步限制为封闭类【内部类所在的外围类】中。

  Java平台库中的几个类违反了公共类不应直接公开字段的建议。显著的例子包括java.awt包中的Point和Dimension类。它们是不值得效仿的例子,相反,这些类应该被当做反面的警告示例。正如第67项所述,暴露Dimension类内部数据造成了严重的性能问题,这个问题至今仍然存在。

  虽然让公有类直接暴露字段永远不是一个好主意,但如果字段是不可变的,这种做法的危害就比较小一点。如果不改变类的API,就无法改变这种类的表示法,当字段被读取的时候,你也无法采取辅助操作,但是可以强加约束条件。例如,这个类确保了每个实例都表示一个有效的时间:

// Public class with exposed immutable fields - questionable
public final class Time {
    private static final int HOURS_PER_DAY = 24;
    private static final int MINUTES_PER_HOUR = 60;
    public final int hour;
    public final int minute;
    public Time(int hour, int minute) {
        if (hour < 0 || hour >= HOURS_PER_DAY)
            throw new IllegalArgumentException("Hour: " + hour);
        if (minute < 0 || minute >= MINUTES_PER_HOUR)
            throw new IllegalArgumentException("Min: " + minute);
        this.hour = hour;
        this.minute = minute;
    }
    ... // Remainder omitted
}

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

第17项:使可变性最小化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值