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

术语:

退化类(degenerate classes):退化类是对类成员的一种限制形式,只保留了数据域,类似于c语言里的结构体。是一种结构化的数据。



        有时候,可能会编写民一些退货类,只是用来集中实例域。

// Degenerate classes like this should not be public!
class Point {
	public double x;
	public double y;
}
        如上这样的类绝不应该声名为public,因为一旦声名为了public,这就变成了API的一部分,客户端可直接操作所有数据域。这些类没有提供封装的功能,如果不改变API,就无法改变它的数据表示法,也无法强加任何约束条件,当被访问的时候,无法采取任何辅助措施,这么多问题,归结原因就是因为如果类声名不当,那么可能会将整个数据域全部暴露给客户端,因此想要以另一种形式展现数据的时候就必须要更改API,而且任何对数据表现形式的改动都将涉及到很多兼容性问题,封闭不当造成的问题统统出现了。坚持面向对象的程序设计人员对这种类深恶痛绝,认为应该用包含私有域和公有访问方法的类来代替,对于可变类来说,应该用包含私有域和仅有设置方法的类代替,也就是应该数据,而提供getter和setter方法:

// 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; }
}
        很显然,当谈论到公有类的时候,坚持面向对象设计思想的看法是正确的:如果类可以在它所在的包的外部进行访问是,就提供访问方法,以保留将来改变该类内部表示法的灵活性。如果公有类暴露了它的数据域,要想在将来改变其内部表示法是不可能的,因为公有类的客户端代码已经遍布各处了。

        然而,如果类是包级私有的,或者是私有的嵌套类,直接暴露它的数据域并没有什么本质的错误。这种方法比访问方法的做法更不会产生视觉混乱,无论是在类定义中,还是在使用该类的客户端代码中。虽然客户端代码与该类的内部表示法紧密相连, 但是这些代码被限定在包含该类的包中。如果有必要,不改变包之外的任何代码而只改变内部的数据表示法也是可以的。在私有的嵌套类的情况下,改变以的作用范围又进一步限制在外围类中。这样问题变得更加不明显了。

        如果域是不可改变的,那么让公有类直接暴露域的害处会比较小一点。但是,如果不改变类的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("Minute: " + minute);
		this.hour = hour;
		this.minute = minute;
	}
	// Remainder omitted
}
        总之,公有类永远都不应该暴露可变的域,有时候会需要用包级私有的或者私有的嵌套类来暴露域,无论这个类的域是可变的还是不可变的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值