# 類別成員中的公有與私有

為了保護資料成員不被任意的修改，在此篇將會談論到透過一個公有私有的機制，來防範這個漏洞。

因此先從私有資料成員開始談論起。

以[本章練習](https://java.4-x.tw/java-08/java-08-p)的範例來舉例：

```
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；\
若設定的值小於零，那麼就直接印出輸入錯誤的訊息

```
moon.setRadius(3);
```

## 注意

初次學程式雖然都是寫單一的小程式練習；\
但日後一定會有大型的專案撰寫，除了學習相關的觀念，同時也是替日後打下強大的基礎。

> 本章的 公有與私有 ( public & private) 除了上述示範是在同一支程式底下運作外，在此也要給一個觀念：
>
> 1. 若冠上 public 公有的成員，可以被 其他程式自由的存取
> 2. 若冠上 private 私有的成員，除了 package 其他程式無法存取外，自身的程式也無法存取；運作的範圍只在該類別當中
> 3. 若省略 公有與私有 ( public & private) 都不使用，那麼成員只會在同一 package 存取使用
