class Point {
public double x;
public double y;
}
這種類數據是可以被直接訪問的,這些類沒有提供封裝的功能,如果不改變API,就無法改變它的數據表示法,也無法強加任何約束條件,當域被訪問的時候,無法采取任何輔助的行動,堅持面向對象程序設計的程序員對這種類深惡痛絕,認為應該用包含私有域和公有訪問方法來代替。對于可變的類來說,應該用包含私有域和公有設值方法的類來代替,就是我們所說的 get和set方法。
class Point {
public double x;
public 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 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){
System.err.println("Error");
}
if(minute < 0|| minute >= MINUTES_PER_HOUR){
System.err.println("Error");}
this.hour = hour;
this.minute = minute;
}
}
總之,公有類永遠都不應該暴露可變的域。