Dân lập trình hẳn không còn xa lạ với OOP và 4 tính chất của nó. Tuy vậy có một tính chất khá quan trọng nhưng thường bị hiểu sai, đó chính là tính trừu tượng (Abstraction).
Hiện tại có kha khá bài viết định nghĩa Abstraction như trên. Lúc trước mình mới học nên không chắc đâu là đúng, đâu là sai, nhưng bây giờ mình tự tin nói rằng định nghĩa như trên là sai hoàn toàn.
Nếu bạn đọc đến đây nhưng chưa thấy sai chỗ nào, thì bài viết này dành cho bạn, hãy tiếp tục đọc nhé.
1. Hiểu lầm về Abstraction
Đây là một khái niệm thường thấy về tính trừu tượng trong OOP.
Abstraction giúp loại bỏ những thứ phức tạp, không cần thiết của đối tượng và chỉ tập trung vào những gì cốt lõi, quan trọng.
Định nghĩa trên không hề chính xác và còn gây hiểu nhầm cho người học. Có hai điểm chưa đúng:
- Cho rằng thực hiện Abstraction là lựa chọn những thông tin cần thiết (loại bỏ hoặc giữ lại)
- Chưa mô tả được cách đạt được Abstraction như thế nào
Theo cách hiểu trên, khi code lúc nào cũng phải dùng Abstraction, do thực tế không thể nào liệt kê tất cả thông tin của object được. Nên nhớ rằng cả 3 tính chất OOP còn lại đều không bắt buộc thực hiện, ví dụ một class có thể không tuân theo tính đóng gói, không có kế thừa cũng như đa hình.
Thêm nữa, nếu định nghĩa như trên thì từ khóa abstract
và interface
dùng làm gì? Như class dưới đây vẫn có abstraction (theo định nghĩa), nhưng lại không động gì tới abstract class hay interface.
// Chỉ có 2 thuộc tính cần thiếtpublicclassPerson{privateString name;privateint age;// Others}
2. Định nghĩa chuẩn cho Abstraction
Như phần trên, chúng ta biết rằng Abstraction không phải là việc “chỉ lựa chọn những thông tin, chức năng cần thiết”. Vậy đâu mới là định nghĩa đúng của Abstraction? Nên hiểu như thế nào cho đúng?
Abstraction là việc chỉ hiển thị các chức năng cần thiết ra bên ngoài, và ẩn đi cách thực hiện bên trong.
Nói cách khác, người dùng chỉ cần biết có thể thực hiện được những gì (what), còn việc thực hiện thế nào thì không cần quan tâm (how).
Khái niệm trên vẫn khá trừu tượng, không sao, abstraction là phải trừu tượng mà 😀 Hãy đi tiếp qua ví dụ bên dưới.
2.1. Câu chuyện về cái remote TV
Mình hay dùng ví dụ này để giải thích cho tính trừu tượng trong OOP.
Bây giờ, mình đưa cho bạn cái remote không có vỏ (phần ở trên) và yêu cầu bạn bật qua kênh 7. Tất nhiên là cuối cùng bạn cũng sẽ tìm được nút nào là kênh 7, nhưng việc đó khá mất thời gian.
Tiếp theo, mình lắp lại phần vỏ cho remote, và yêu cầu bạn chuyển qua kênh 5. Easy game, right?
Như vậy, cái remote không có vỏ vẫn là cái remote, vẫn sử dụng được bình thường. Tuy nhiên, nếu có thêm lớp vỏ bên ngoài nữa thì việc sử dụng sẽ dễ dàng hơn.
2.2. Bản chất của Abstraction
Bản chất của abstraction là thêm một layer đơn giản hơn để sử dụng, nhằm ẩn đi những thứ phức tạp bên trong.
Như ví dụ về cái remote TV ở trên, phần vỏ chính là abstraction layer. Phần vỏ có những nút có ký hiệu, màu sắc dễ dàng sử dụng, còn khi bấm nút thì bên trong hoạt động thế nào, dòng điện chạy ra sao không cần quan tâm.
Abstraction trong OOP có 2 loại:
- Data abstraction: ẩn thông tin của đối tượng với bên ngoài
- Process abstraction: ẩn cách triển khai của các chức năng
Như vậy, Abstraction phải là quá trình ẩn đi thông tin và cách triển khai của chức năng, chứ không phải việc lựa chọn những gì cần thiết đưa vào đối tượng.
2.3. Sự mơ hồ trong định nghĩa
Hãy xem xét tiếp một định nghĩa khác như sau, nguồn từ Guru99, đoạn đầu tiên.
Abstraction is the concept of object-oriented programming that “shows” only essential attributes and “hides” unnecessary information.
The main purpose of abstraction is hiding the unnecessary details from the users.
Abstraction is selecting data from a larger pool to show only relevant details of the object to the user.
Khái niệm này khá tương đồng với định nghĩa mình nêu ở trên. Tuy nhiên, nó vẫn còn mơ hồ:
- Làm người đọc ngầm hiểu chỉ có một đối tượng duy nhất. Không phân biệt ra abstraction layer và implementation làm người học khó hình dung.
- Chưa nêu rõ cách “show”, “hide”, “selecting data” như thế nào. Có phải là dùng từ khóa
public
để show, còn lại thì dùngprivate
để ẩn đi? (Đúng ra phải nói dùngabstract class
vàinterface
để tạo ra abstraction layer mới và sử dụng nó).
Như vậy, qua quá trình “tam sao thất bản”, mỗi người giải thích theo một cách khác nhau đã làm sai lệch đi định nghĩa của tính trừu tượng trong OOP. Hi vọng các bạn đọc được bài viết này sẽ hiểu được chính xác và không còn bị mơ hồ khi nói đến Abstraction nữa.
Một số nguồn mình có tham khảo và tìm dẫn chứng cho bài này. Bài viết khá rõ ràng và dễ hiểu, nên đọc nhé.
https://www.journaldev.com/33191/what-is-abstraction-in-oops
https://www.guru99.com/java-data-abstraction.html
Bonus, mình có thử google thì có một post Stack Overflow nói về vấn đề này, nhưng không được quan tâm lắm.
https://stackoverflow.com/questions/64520515/what-is-the-correct-definition-of-abstract-in-oop
Nguồn: viblo.asia