Tính đóng gói (Encapsulation) trong lập trình hướng đối tượng

Một trong số 4 tính chất đặc trưng chung của các ngôn ngữ lập trình hướng đối tượng (OOP) như C++, C#, Java, Objective-C… đó là tính đóng gói (Encapsulation). Đây là khái niệm rất cơ bản khi các bạn học về lập trình hướng đối tượng nhưng tôi thì hầu như chẳng mấy khi quan tâm định nghĩa chính xác nó là gì. Bởi vì các bạn biết đấy, với những thứ mà chúng ta gặp hoặc tiếp xúc liên tục trong thời gian dài, khi chúng ta đã quá hiểu chúng rồi thì chúng ta nhiều khi lại không có ý tưởng rõ ràng về việc định nghĩa chúng. Ví dụ, tôi chắc chắn rằng tôi biết rất rõ những thứ như con chó, con gà, xe máy,… là gì nhưng để đưa ra một khái niệm chuẩn xác thì chắc là tôi cũng cần thời gian đấy.

Gần đây có một số bạn hỏi tôi về các tính chất của lập trình OOP trong đó có tính đóng gói (Encapsulation), tôi nhận thức được việc trả lời các bạn (đặc biệt là các bạn mới học) một cách đúng bản chất ngay từ đầu là rất quan trọng. Do đó, để có thể trả lời các bạn một cách chuẩn xác nhất thì tôi đã phải search lại một vòng Google xem định nghĩa mà tôi đưa ra có đúng không. Và kết quả làm tôi giật mình một chút, tôi đã tham khảo khá nhiều link, và đa số kết quả đều có một cái gì đó sai sai. Hầu hết các kết quả (cả tiếng Anh, lẫn tiếng Việt) đều có một vấn đề, đó là mặc dù đang nói về tính đóng gói nhưng lại ít nhiều hoặc thậm chí mang nguyên khái niệm về che dấu dữ liệu (Data Hiding) vào để giải thích mặc dù đó là một khái niệm hoàn toàn khác. Ngay cả giải thích ở link wiki này tôi thấy cũng không đúng lắm. Chính vì việc giải thích sai, không rõ ràng hoặc dễ gây nhầm lẫn đó nên hôm nay tôi viết bài viết này để đưa ra cách giải thích mà tôi cho là dễ hiểu và hợp lý nhất, rất may là cũng có một số người đồng quan điểm với tôi, tôi sẽ trích một số link tôi đã tham khảo mà tôi thấy họ giải thích về Encapsulation khá hợp lý ở cuối bài viết này.

Vậy rốt cục Tính đóng gói – Encapsulation là gì ? Tôi xin đúc rút lại như sau:

Tính đóng gói (Encapsulation) chỉ đơn giản là việc kết hợp một bộ các dữ liệu (data) liên quan đến nhau cùng với một bộ các hàm/phương thức (functions/methods) hoạt động trên các dữ liệu đó, “gói” tất cả vào trong một cái gọi là class.  Các thực thể của các class thì được gọi là các đối tượng (objects) trong khi class giống như một công thức được sử dụng để tạo ra các đối tượng đó.

Các bạn xem thêm về định nghĩa class và object tại đây:

Một ví dụ đơn giản về tính đóng gói như sau. Trước tiên các bạn hãy xem qua đoạn code viết bằng C++ sau →

Tính đóng gói thể hiện ở đoạn code trên là việc tôi kết hợp các dữ liệu về hình chữ nhật gồm có chiều rộng, chiều dài cùng với các hàm xử lý (đọc/ghi/tính toán) với các dữ liệu này vào một class có tên là Rectangle. Chỉ đơn giản vậy thôi.

Bây giờ tôi sẽ nói một chút về Che dấu dữ liệu – Data Hiding  mà hay bị đánh đồng lẫn lỗn với Encapsulation. 

Che dấu dữ liệu  (Data Hiding) là việc một số dữ liệu (data) và hàm/phương thức (functions/methods) được class che giấu đi (ở dạng private) để đảm bảo rằng các dữ liệu đó sẽ được truy cập và sử dụng đúng mục đích, đúng cách thông qua các hàm/phương thức (functions/methods) ở dạng public mà class cung cấp. Bạn không thể truy cập đến các private data hoặc gọi đến private methods của class từ bên ngoài class đó.

Che dấu dữ liệu – Data Hiding chỉ là một phương pháp kỹ thuật mà bạn áp dụng để xây dựng nên class mà thôi, nó không phải là tính chất đặc trưng của lập trình hướng đối tượng, việc bạn có áp dụng phương pháp này hay không là hoàn toàn không bắt buộc. Tuy nhiên trong các hệ thống thật, để nâng cao tính security, giảm phục thuộc giữa các class, tránh lỗi do đọc ghi dữ liệu sai cách, …  thì việc áp dụng phương pháp che dấu dữ liệu gần như là đương nhiên.

Nhìn lại đoạn code sample bên trên các bạn có thể thấy là các data như mWidth, mHeight được để ở dạng private. Bạn chỉ có thể truy cập chúng thông qua các phương thức public như: setValues(), getArea() → đó chính là Data Hiding.

Tham khảo

Xem thêm

— Phạm Minh Tuấn (Shun) —