iT邦幫忙

2023 iThome 鐵人賽

DAY 8
0
自我挑戰組

轉職仔自學Java筆記本系列 第 18

封裝 Encapsulation

  • 分享至 

  • xImage
  •  

繞了一大圈終於要開始寫物件導向的核心概念了。

封裝 Encapsulation 的概念

首先,第一個要分享的是封裝 (Encapsulation),封裝的概念是把資料包在物件之中,讓使用者只能採用公開的特定方法才可以取得可查詢的資料,其他類別內部的方式與資料都是無法直接取用的。這是一種資料保護的方式,可避免資料被任意的更改,也強化的物件之間的獨立。

以車輛舉例來說,如果車子是一個物件,無法從外面看到他目前的油量、里程數等等資訊,這些就是被封裝在車子這個物件中的資料。必須拿正確的感應器以「發動」這個方法發動車輛後,才會去執行顯示電子儀表板,讓人查看到車輛的資訊。

class 車輛 {
	
	// 油量, 里程數...都是封裝在車輛物件的屬性 
	private int 油量;
	private int 里程數;
	
	// 啟動程序, 顯示儀表板...都是封裝在車輛物件的方法,外部無法訪問
	private void 啟動程序{
		...
	}

	private void 顯示儀表板{
		show(油量, 里程數)
		...
	}
	
	// ** 開放 ** 給使用者訪問的方法
	public void 發動(int 感應器ID){
		if (感應器 == XXXX){
				啟動程序();
				顯示儀表板();
		}
	}

}

未封裝的風險

如果沒有被做好封裝的物件,就會有機率因為外部的訪問,而產生錯誤的結果。

舉例來說,如果有一台車的物件,內部含有廠牌, 售價的屬性:

// 定義 Car 類別 但是開放屬性可供訪問

class Car{
		public String brand = "BMW";
		public int price = 25000;
		...

		public void sell(){
				System.out.println("This car sells for " + price + " dollars.");
		}
}



// 創建一個物件 car
Car car = new Car();

// 因為是 public 屬性可以被直接訪問
System.out.println(car.price);
// Out: 25000

car.sell();
// Out: This car sells for 25000 dollars.

// 但也可以直接被外部修改
car.price = -1000;
car.sell();
// Out: This car sells for -1000 dollars.

從上面的例子發現,我們都知道一台車售價是 -1,000 鎂是完全不合理的,但如果開放屬性被訪問的話,就很難避免外部直接對屬性或方法進行修改,產生意料之外的結果。

private 與 setter/getter 的應用

因此,為達成 Encapsulation 的目標,在定義類別時,我們通常會將屬性與不想被訪問的內部方法盡可能的設定成 private,若是要從外部更改獲釋存取,則會建立方法 setter 和 getter 或其他公開方法,來管控存取屬性的方法。所以把剛剛的範例改寫成這樣。

class Car{
				
				// 將屬性設置為 private
        private String brand = "BMW";
        private int price = 25000;

        public void sell(){
            System.out.println("This car sells for " + price + " dollars.");
        }
				
				// 增加 setter 和 getter
        public int getPrice() {
            return price;
        }

        public void setPrice(int price) {

			// 限制 price 必須大於兩萬,否則會發出提醒
            if (price >= 20000) {
                this.price = price;
            } else {
                System.out.println("Error: price need to over 20,000 dollars");
            }

        }
---

// 創建一個物件 car
Car car = new Car();

car.price // 無法被訪問

// 要使用 getter 才能取得 price
car.getPrice() 

// 使用 setter 設定 price 值
car.setPrice(-1000); 
// Error: price need to over 20,000 dollars
// 可以排除不符合規則的輸入

透過 private 的設定,還有 getter & setter 等公開方法的管控,可增加程式的穩定度,達到封裝Encapsulation 的效果。


上一篇
物件導向設計與 Java
下一篇
繼承 Inheritance
系列文
轉職仔自學Java筆記本22
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言