天天看點

建議:在公有類中使用通路方法而非公有域。

有時候,可能會編寫一些退化類(degenerate classes),沒有什麼作用,隻是用來集中執行個體域:

// Degenerate classes like this should not be public!

class Point {

public double x;

public double y;

}
           

由于這種類的資料域是可以被直接通路的,這些類沒有提供封裝(encapsulation)的功能。如果不改變API,就無法改變他的資料表示法,也無法強加任何限制條件;當域被通路的時候,無法采取任何輔助的行動。堅持面向對象程式設計的程式員對這種類深惡痛絕,認為應該包含私有域和公有通路方法(getter)的類代替。對于可變的類來說,應該用包含私有域和公有設值方法(setter)的類代替:

// Encapsulation of data by accessor methods and mutators

class Point {

pirvate 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類。他們是不值得仿效的例子,相反,這些類應該被當做反面的警告示例。

總之,公有類永遠都不應該暴露可變的域。雖然還是有問題,但是讓公有類暴露不可變的域其危害比較小。但是,有時候會需要用包級私有的或者私有的嵌套類來暴露域,無論這個類是可變的還是不可變的。