資訊隱藏和封裝之間的區別
1. 概述
封裝是一種重要的物件導向程式設計範式。它允許將資料和方法組合到一個類別中。然而,封裝本身並不能保證防禦性程式設計。
為了實現穩健性,我們採用資訊隱藏。資訊隱藏是一種程式設計原則,它提倡限制對內部實現細節的存取的想法。
在本教程中,我們將探討有關封裝和資訊隱藏的詳細資訊。此外,我們將看到一些範例程式碼並了解這兩個概念之間的主要差異。
二、歷史背景
「資訊隱藏」一詞是 Parnas 在 1972 年創造的,試圖區分過程式編程和模組化編程。
Parnas 推斷外部模組應該不知道資料的實作。
此外,1973 年,Zelis 提出了封裝這個詞來解釋如何減少對類別中底層資料的訪問,以防止不必要的修改。
1978 年, Parnas聲稱封裝和資訊隱藏是同義詞。然而,2001年,Paul Roger透過範例程式碼展示了封裝和資訊隱藏之間的差異。他聲稱我們可以在不隱藏訊息的情況下進行封裝。
封裝是物件導向程式設計中的一個廣泛概念,它將資料與方法捆綁在一起。這確保了模組化設計。
封裝和資訊隱藏有時是同義詞,但也有一些區別。
3、封裝
根據 Paul Roger 的說法,封裝只是將資料與作用於資料的操作捆綁在一起。
3.1.無封裝
讓我們來看一個沒有封裝的範例類別:
class Book {
public String author;
public int isbn;
}
在這裡, Book
類別的欄位具有public
存取修飾符。這使得可以從外部類別存取這些欄位。
讓我們建立另一個名為BookDetails
的類別來取得Book
物件的詳細資訊:
class BookDetails {
public String bookDetails(Book book) {
return "author name: " + book.author + " ISBN: " + book.isbn;
}
}
BookDetails
類別包含一個使用Book
資料的方法。在這裡,我們將Book
類別視為資料的容器,將BookDetails
視為作用於資料的方法的集合。
我們使用一個程式設計過程來強制創建一個對來自另一個類別的資料進行操作的實作類別。這種程式風格很古老,而且不是模組化的。
這是獲取一本書詳細資訊的單元測試:
@Test
void givenUnencapsulatedClass_whenImplementationClassIsSeparate_thenReturnResult() {
Book myBook = new Book();
myBook.author = "JK Rowlings";
myBook.isbn = 67890;
BookDetails details = new BookDetails();
String result = details.bookDetails(myBook);
assertEquals("author name: " + myBook.author + " ISBN: " + myBook.isbn, result);
}
上面的實作可以透過封裝來簡化。 Book
類別的變更會影響任何使用Book
資料的類別。
3.2.帶封裝
讓我們使用封裝來改進上一節中的設計。我們可以將資料和對其進行操作的方法捆綁到一個類別中:
class BookEncapsulation {
public String author;
public int isbn;
public BookEncapsulation(String author, int isbn) {
this.author = author;
this.isbn = isbn;
}
public String getBookDetails() {
return "author name: " + author + " ISBN: " + isbn;
}
}
在這裡,我們透過將實作與類別捆綁在一起來改進程式碼。這使得程式碼模組化。客戶端可以輕鬆呼叫getBookDetails()
方法,而無需了解其實作。
讓我們來看看呼叫getBookDetails()
單元測試:
@Test
void givenEncapsulatedClass_whenDataIsNotHidden_thenReturnResult() {
BookEncapsulation myBook = new BookEncapsulation("JK Rowlings", 67890);
String result = myBook.getBookDetails();
assertEquals("author name: " + myBook.author + " ISBN: " + myBook.isbn, result);
}
封裝改進了程式碼,但外部類別可以修改Book
數據,因為欄位使用public
存取修飾符。然而,封裝對於使用哪個存取修飾符沒有嚴格的規則。我們可以使用public
、 private
和protected
存取修飾符。
此外,封裝有助於向類別引入功能,而不會破壞使用該類別的外部程式碼。讓我們透過引入id
來修改BookEncapsulation
類別:
// ...
public int id = 1;
public BookEncapsulation(String author, int isbn) {
this.author = author;
this.isbn = isbn;
}
public String getBookDetails() {
return "author id: " + id + " author name: " + author + " ISBN: " + isbn;
}
// ...
這裡,我們引入id
欄位並修改getBookDetails().
這些內部變更不會破壞任何客戶端程式碼。這使得封裝變得強大且模組化。
然而,我們可以透過應用「資訊隱藏」的思想,使封裝更加嚴格。對於防禦性程式來說,封裝是不夠的。我們需要透過封裝來應用資訊隱藏,以防止不必要的資料修改。
4. 訊息隱藏
資訊隱藏是一種程式設計原理,旨在防止直接修改類別的資料。此外,它還提供了存取和修改類別資料的嚴格指南。
此外,它有助於向客戶隱藏設計實現,尤其是可能更改的設計實現。
此外,與封裝一起使用時的資訊隱藏可確保模組化程式碼。
讓我們透過應用資訊隱藏來改進封裝類別:
class BookInformationHiding {
private String author;
private int isbn;
private int id = 1;
public BookInformationHiding(String author, int isbn) {
setAuthor(author);
setIsbn(isbn);
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public int getIsbn() {
return isbn;
}
public void setIsbn(int isbn) {
this.isbn = isbn;
}
public String getBookDetails() {
return "author id: " + id + " author name: " + author + " ISBN: " + isbn;
}
}
在這裡,我們使用private
存取修飾符來限制外部類別對欄位的存取和變更。此外,我們建立 getter 和 setter 來設定如何存取和修改欄位。
與可以使用任何存取修飾符的沒有資訊隱藏的封裝相反,資訊隱藏是透過使用private
存取修飾符來實現的。這僅限制對類內字段的存取。
這些欄位不能直接從客戶端程式碼訪問,從而使其更加健壯。
讓我們看一下修改後的類別的單元測試:
@Test
void givenEncapsulatedClass_whenDataIsHidden_thenReturnResult() {
BookInformationHiding myBook = new BookInformationHiding("JK Rowlings", 67890);
String result = myBook.getBookDetails();
assertEquals("author id: " + 1 + " author name: " + myBook.getAuthor() + " ISBN: " + myBook.getIsbn(), result);
}
此外,我們可以針對如何修改資料製定嚴格的規則。例如,我們可以透過修改 setter 來避免負 ISBN:
public void setIsbn(int isbn) {
if (isbn < 0) {
throw new IllegalArgumentException("ISBN can't be negative");
}
this.isbn = isbn;
}
在這裡,我們對如何修改 ISBN 創建了嚴格的規則。
5. 主要差異
下面的匯總表顯示了封裝和資訊隱藏之間的主要區別:
訊息隱藏 | 封裝 |
隱藏實作細節與意外資料修改的設計原則 | 物件導向的原則,將資料與對其進行操作的函數捆綁在一起。 |
嚴格使用private 存取修飾符 | 對存取修飾符不嚴格,可以使用public 、 private 或protected 存取修飾符 |
有助於實現防禦性編程 | 一種實現資訊隱藏的方法 |
六,結論
在本文中,我們學習了封裝和資訊隱藏的關鍵概念。此外,我們還看到了範例程式碼,顯示了封裝和資訊隱藏之間的細微差別。
然而,有一個學派認為資訊隱藏和封裝是同義詞。在封裝類別時,我們需要始終應用資訊隱藏的原則。
與往常一樣,範例的原始程式碼可在 GitHub 上取得。