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

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

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

以[本章練習](/java-08/java-08-p.md)的範例來舉例：

```
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 存取使用


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://java.4-x.tw/java-08/java-08-8.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
