為了保護資料成員不被任意的修改,在此篇將會談論到透過一個公有私有的機制,來防範這個漏洞。
因此先從私有資料成員開始談論起。
以本章練習的範例來舉例:
class Circle{ //定義類別Circle
double pi=3.14;
double radius;
void show_area()
{
System.out.println("面積= "+pi*radius*radius);
}
}
public class ch08_3 {
public static void main(String[] args) {
Circle moon=new Circle(); //建立 moon 物件
moon.pi=3.1415;
moon.show_area();
}
}
在資料成員的部分,我們有 pi與 radius;
因為這是一個計算圓面積的程式,在主程式設值給資料成員 radius 聽起來很正常;
雖然主程式並無設值給 pi,但 pi 很有可能因為程式的規模一大,而導致值會有所變更;
同理, radius 也有可能在此時設值為 2 ,但又可能遭到修改。
為了防範此類事情發生,有了 公有與私有 ( public & private) 的機制。
私有
class Circle{ //定義類別Circle
private double pi=3.14;
private double radius;
.....
}
直接在宣告最前方,個別加上 private ,如此一來將無法從類別以外的地方 設定或直接讀取。
進而達到保護的效果。
class Circle{ //定義類別Circle
private double pi=3.14;
private double radius;
void show_area()
{
System.out.println("面積= "+pi*radius*radius);
}
}
在類別函數成員的部分,是可以正常讀取到私有成員 pi 與 radius 的。
public static void main(String[] args) {
Circle moon=new Circle(); //建立 moon 物件
moon.radius=-3;
moon.show_area();
}
但在主程式的部分,就無法設值給 radius 了。
公有
既然有 私有 private 就有 公有 public
剛剛的程式碼,設定 private 之後,也無法設值計算圓面積,那到底保護了資料成員又有何作用?
將上述的程式做一個修改,成一個較完善的程式,就會慢慢清楚囉~:
class Circle{ //定義類別Circle
private double pi=3.14;
private double radius;
// 設定資料成員為私有
private double area()
{ //設定計算面積的函數為私有
return pi*radius*radius;
}
public void show_area()
{ //設定列印面積的函數為公有
System.out.println("area="+ area());
}
public void setRadius(double r)
{ //設定一個設定半徑的函數為公有
if (r>0)
{
radius=r;
System.out.println("radius= "+radius);
}
else System.out.println("半徑輸入錯誤");
}
}
public class ch08_3 {
public static void main(String[] args) {
Circle moon=new Circle(); //建立 moon 物件
moon.setRadius(3);
moon.show_area();
}
}
以下來一步步講解:
首先是類別的部分,設為私有的除了資料成員外,也設定函數成員area 為私有
private double pi=3.14;
private double radius;
// 設定資料成員為私有
private double area()
{ //設定計算面積的函數為私有
return pi*radius*radius;
}
可以注意到,area 函數 單純為一個計算值的函數。
再來看到設定公有的函數:
分別有 呼叫列印面積的函數
public void show_area()
{ //設定列印面積的函數為公有
System.out.println("area="+ area());
}
以及設定半徑的函數
public void setRadius(double r)
{ //設定一個設定半徑的函數為公有
if (r > 0)
{
radius=r;
System.out.println("radius= "+radius);
}
else System.out.println("半徑輸入錯誤");
}
主程式方面,由於無法呼叫私有的函數或直接設值給私有資料成員;
因此在此是呼叫公有函數
public static void main(String[] args) {
Circle moon=new Circle(); //建立 moon 物件
moon.setRadius(3);
moon.show_area();
}
這樣有什麼好處呢?除了可以判斷輸入的值是否正確之外,還可以有效保護資料成員不被程式任意的更改。
呼叫設值函數時:會傳進 if else 做判斷,若半徑大於零 就設定 剛剛傳進的值 r 給 radius;
若設定的值小於零,那麼就直接印出輸入錯誤的訊息
注意
初次學程式雖然都是寫單一的小程式練習;
但日後一定會有大型的專案撰寫,除了學習相關的觀念,同時也是替日後打下強大的基礎。
本章的 公有與私有 ( public & private) 除了上述示範是在同一支程式底下運作外,在此也要給一個觀念:
若冠上 public 公有的成員,可以被 其他程式自由的存取
若冠上 private 私有的成員,除了 package 其他程式無法存取外,自身的程式也無法存取;運作的範圍只在該類別當中
若省略 公有與私有 ( public & private) 都不使用,那麼成員只會在同一 package 存取使用