有时候,可能需要编写一些退化类,它们没有什么作用,只是用来集中实例域 :
class Point {
public double x;
public double y;
}
由于这种类的数据域是可以被直接访问的,这些类没有提供封装( encapsulation )的功能。 如果不改变 API,就无法改变它的数据表示法, 也无法强加任何约束条件;当域被访问的时候,无法采取任何辅助的行动 。 坚持面向对象编程的程序员对这种类深恶痛绝,认为应该用包含私有域和公有访问方法( getter ) 的类代替 。 对于可变的类来说,应该用公有设值方法( setter )的类代替 :
class Point {
private double x;
private double y;
pub1ic 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 ,就无法改变这种类的表示法,当域被读取的时候,你也无法采取辅助的行动,但是可以强加约束条件 。 例如,这个类确保了每个实例都表示一个有效的时间:文章来源:https://www.toymoban.com/news/detail-576803.html
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
}
简而言之,公有类永远都不应该暴露可变的域 。 虽然还是有问题,但是让公有类暴露不可变的域,其危害相对来说比较小 。 但有时候会需要用包级私有的或者私有的嵌套类来暴露域,无论这个类是可变的还是不可变的 。文章来源地址https://www.toymoban.com/news/detail-576803.html
到了这里,关于Effective Java笔记(16)要在公有类而非公有域中使用访问方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!