1. Giới thiệu

Chúng tôi muốn dành bài học hôm nay để đóng gói . Bạn đã biết nó là gì trong điều kiện chung.

đóng gói

Những lợi ích của việc đóng gói là gì? Có khá nhiều trong số chúng, nhưng tôi có thể chỉ ra bốn cái, theo ý kiến ​​​​của tôi, là những cái chính:


2. Trạng thái bên trong hợp lệ

Trong các chương trình, các tình huống thường phát sinh khi một đối tượng tương tác với một số lớp khác. Những tương tác này với đối tượng có thể làm hỏng dữ liệu bên trong đối tượng, khiến đối tượng không thể tiếp tục hoạt động như mong đợi.

Do đó, đối tượng cần theo dõi bất kỳ thay đổi nào đối với dữ liệu nội bộ của nó hoặc tốt hơn là tự thực hiện các thay đổi.

Nếu chúng ta không muốn một số biến bị thay đổi bởi các lớp khác, thì chúng ta khai báo nó là private. Khi chúng tôi làm điều đó, chỉ các phương thức của lớp riêng của nó mới có thể truy cập nó. Nếu chúng ta muốn các biến ở chế độ chỉ đọc, thì chúng ta cần thêm a public gettercho các biến có liên quan.

Ví dụ: giả sử chúng tôi muốn mọi người có thể biết số lượng phần tử trong bộ sưu tập của mình, nhưng chúng tôi không muốn họ có thể thay đổi bộ sưu tập mà không có sự cho phép của chúng tôi. Sau đó, chúng ta khai báo một private int countbiến và một public getCount()phương thức.

Việc sử dụng đóng gói đúng cách đảm bảo rằng không lớp nào có thể truy cập trực tiếp vào dữ liệu nội bộ của lớp chúng tôi, do đó ngăn chặn bất kỳ thay đổi nào ngoài tầm kiểm soát của chúng tôi. Những thay đổi này chỉ có thể thực hiện được thông qua việc gọi các phương thức của cùng một lớp với các biến được thay đổi.

Tốt nhất là giả định rằng các lập trình viên khác sẽ luôn sử dụng các lớp của bạn theo cách thuận tiện nhất cho họ chứ không phải theo cách an toàn nhất cho bạn (cho lớp của bạn). Hành vi này là nguồn gốc của cả lỗi cũng như nỗ lực ngăn chặn chúng.


3. Xác thực đối số phương thức

Đôi khi chúng ta cần xác thực các đối số được truyền cho các phương thức của mình. Ví dụ: giả sử chúng ta có một lớp đại diện cho một người và cho phép bạn đặt ngày sinh. Chúng ta phải kiểm tra tất cả dữ liệu đầu vào để đảm bảo nó phù hợp với logic của chương trình và logic của lớp chúng ta. Ví dụ: không cho phép ngày sinh vào tháng thứ 13 hoặc vào ngày 30 tháng 2, v.v.

Tại sao ai đó sẽ chỉ ra ngày 30 tháng 2 cho ngày sinh của họ? Đầu tiên, đây có thể là lỗi của người dùng khi nhập dữ liệu. Thứ hai, một chương trình có thể có nhiều lỗi trước khi nó bắt đầu chạy như kim đồng hồ. Ví dụ, tình huống sau đây là có thể.

Một lập trình viên viết một chương trình xác định những người có sinh nhật vào ngày mốt. Ví dụ: giả sử hôm nay là ngày 3 tháng 3. Chương trình sẽ thêm số 2 vào ngày hiện tại của tháng và tìm kiếm tất cả những người sinh ngày 5 tháng 3. Có vẻ như mọi thứ đều đúng.

Nhưng khi đến ngày 30 tháng 3, chương trình sẽ không tìm thấy ai, vì lịch không có ngày 32 tháng 3. Một chương trình sẽ ít lỗi hơn nhiều nếu chúng ta kiểm tra dữ liệu được truyền cho các phương thức.

Hãy nhớ khi chúng tôi nghiên cứu ArrayListvà phân tích mã của nó? Chúng ta đã thấy rằng các phương thức getsetđã kiểm tra xem có indexlớn hơn hoặc bằng 0 và nhỏ hơn độ dài của mảng hay không. Hơn nữa, các phương thức này đưa ra một ngoại lệ nếu chỉ mục nằm ngoài giới hạn của mảng. Đây là một ví dụ cổ điển về xác thực đầu vào.


4. Giảm thiểu sai sót khi đổi mã

Giả sử chúng tôi đã viết một lớp siêu hữu ích khi chúng tôi tham gia vào một dự án lớn. Mọi người đều thích nó đến nỗi các lập trình viên khác bắt đầu sử dụng nó ở hàng trăm vị trí trong mã của họ.

Lớp học rất hữu ích nên bạn đã quyết định cải tiến nó. Nhưng nếu bạn loại bỏ bất kỳ phương thức nào khỏi lớp, thì mã của hàng chục người sẽ ngừng biên dịch. Họ sẽ phải viết lại mọi thứ. Và bạn càng thực hiện nhiều thay đổi, bạn sẽ càng tạo ra nhiều lỗi hơn. Bạn sẽ phá vỡ rất nhiều hội đồng và bạn sẽ bị ghét.

Nhưng khi chúng ta thay đổi các phương thức được khai báo là riêng tư, chúng ta biết rằng không có một lớp nào khác ở bất kỳ đâu có thể gọi các phương thức này. Chúng tôi có thể viết lại chúng, thay đổi số lượng tham số và loại của chúng và bất kỳ mã bên ngoài phụ thuộc nào sẽ tiếp tục hoạt động. Vâng, ít nhất nó sẽ biên dịch.


5. Chúng tôi quyết định cách đối tượng của chúng tôi tương tác với các đối tượng bên ngoài

Chúng tôi có thể hạn chế một số hành động có thể được thực hiện với đối tượng của mình. Ví dụ: giả sử chúng ta muốn một đối tượng chỉ được khởi tạo một lần. Ngay cả khi nó có thể được tạo ở một số nơi trong dự án. Và chúng ta có thể làm điều này nhờ đóng gói.

đóng gói 2

Đóng gói cho phép chúng tôi thêm các hạn chế bổ sung , có thể biến thành các lợi thế bổ sung . Ví dụ, Stringlớp được triển khai như một đối tượng bất biến . Một đối tượng của Stringlớp là bất biến từ thời điểm nó được tạo ra cho đến thời điểm nó chết. Tất cả các phương thức của Stringlớp ( remove, substring, ...), trả về một chuỗi mới mà không thực hiện bất kỳ thay đổi nào đối với đối tượng mà chúng được gọi.

Đóng gói là một điều rất thú vị.