4 Tính Chất Của Lập Trình Hướng Đối Tượng
Lập trình hướng đối tượng (OOP) là một mô hình lập trình mạnh mẽ và phổ biến, tập trung vào việc tổ chức code thành các “đối tượng” chứa dữ liệu (thuộc tính) và hành vi (phương thức). Để hiểu rõ về OOP, cần nắm vững 4 tính chất của lập trình hướng đối tượng: tính đóng gói (Encapsulation), tính kế thừa (Inheritance), tính đa hình (Polymorphism) và tính trừu tượng (Abstraction).
Tính Đóng Gói (Encapsulation)

Khái niệm
Tính đóng gói là quá trình kết hợp dữ liệu (thuộc tính) và các phương thức (hành vi) liên quan đến dữ liệu đó vào trong một đơn vị duy nhất, gọi là lớp. Nó giống như việc “đóng gói” tất cả các thành phần liên quan đến một đối tượng vào trong một hộp. Mục đích chính của tính đóng gói là bảo vệ dữ liệu khỏi sự truy cập trực tiếp từ bên ngoài và đảm bảo tính toàn vẹn của dữ liệu.
Cơ chế hoạt động
Tính đóng gói được thực hiện thông qua việc sử dụng các cấp độ truy cập (access modifiers) như private, protected và public.
Private: Các thành viên (thuộc tính và phương thức) được khai báo là private chỉ có thể được truy cập từ bên trong lớp đó. Điều này đảm bảo rằng dữ liệu bên trong đối tượng không thể bị thay đổi trực tiếp từ bên ngoài.
Protected: Các thành viên được khai báo là protected có thể được truy cập từ bên trong lớp đó và từ các lớp con (lớp kế thừa) của lớp đó.
Public: Các thành viên được khai báo là public có thể được truy cập từ bất kỳ đâu.
Thông thường, các thuộc tính của một lớp sẽ được khai báo là private hoặc protected, và các phương thức để truy cập và thay đổi các thuộc tính này (getter và setter) sẽ được khai báo là public. Điều này cho phép kiểm soát quyền truy cập vào dữ liệu và đảm bảo rằng dữ liệu chỉ được thay đổi thông qua các phương thức được định nghĩa sẵn.
Ưu điểm của tính đóng gói
Bảo vệ dữ liệu: Ngăn chặn truy cập trực tiếp vào dữ liệu, giảm nguy cơ dữ liệu bị thay đổi một cách không mong muốn.
Tính linh hoạt: Dễ dàng sửa đổi code bên trong mà không ảnh hưởng đến các phần khác của chương trình.
Khả năng tái sử dụng: Mã đã đóng gói có thể được tái sử dụng trong nhiều ứng dụng khác nhau.
Dễ bảo trì: Giúp mã nguồn dễ đọc, dễ hiểu và dễ bảo trì hơn.
Tính Kế Thừa (Inheritance)

Khái niệm
Tính kế thừa là khả năng một lớp (lớp con/subclass) kế thừa các thuộc tính và phương thức của một lớp khác (lớp cha/superclass). Lớp con có thể sử dụng lại các thành phần đã được định nghĩa trong lớp cha, đồng thời có thể mở rộng hoặc sửa đổi các thành phần này để phù hợp với nhu cầu của mình. Tính kế thừa thể hiện mối quan hệ “là một” (is-a) giữa các lớp.
Các loại kế thừa
Có nhiều loại kế thừa khác nhau:
Đơn kế thừa (Single Inheritance): Một lớp chỉ có thể kế thừa từ một lớp duy nhất.
Đa kế thừa (Multiple Inheritance): Một lớp có thể kế thừa từ nhiều lớp. Tuy nhiên, đa kế thừa có thể gây ra các vấn đề phức tạp và không được hỗ trợ trong một số ngôn ngữ lập trình như Java (Java sử dụng interface để thay thế).
Đa cấp kế thừa (Multilevel Inheritance): Một lớp kế thừa từ một lớp khác, và lớp đó lại kế thừa từ một lớp khác nữa.
Phân cấp kế thừa (Hierarchical Inheritance): Nhiều lớp con kế thừa từ một lớp cha duy nhất.
Kế thừa lai (Hybrid Inheritance): Kết hợp nhiều loại kế thừa khác nhau.
Ưu điểm của tính kế thừa
Tái sử dụng mã: Giảm thiểu sự trùng lặp code và tăng hiệu quả phát triển.
Mở rộng chương trình: Dễ dàng thêm các lớp mới dựa trên các lớp đã có.
Tổ chức code: Tạo ra cấu trúc phân cấp rõ ràng, giúp code dễ đọc, dễ hiểu và dễ bảo trì.
Tính Đa Hình (Polymorphism)

Khái niệm
Tính đa hình cho phép một đối tượng có thể có nhiều hình thái khác nhau hoặc thể hiện các hành vi khác nhau dựa trên ngữ cảnh sử dụng. “Đa hình” có nghĩa là “nhiều hình thức”. Trong OOP, tính đa hình cho phép các đối tượng thuộc các lớp khác nhau phản ứng với cùng một thông điệp (ví dụ: gọi một phương thức) theo cách riêng của chúng.
Các loại đa hình
Có hai loại đa hình chính:
Đa hình tĩnh (Compile-time Polymorphism): Được thực hiện thông qua nạp chồng phương thức (method overloading) và nạp chồng toán tử (operator overloading). Trong đa hình tĩnh, trình biên dịch biết chính xác phương thức nào sẽ được gọi tại thời điểm biên dịch.
Đa hình động (Run-time Polymorphism): Được thực hiện thông qua kế thừa và ghi đè phương thức (method overriding). Trong đa hình động, phương thức nào sẽ được gọi được quyết định tại thời điểm chạy, dựa trên kiểu thực tế của đối tượng.
Ưu điểm của tính đa hình
Linh hoạt: Cho phép viết code có thể làm việc với các đối tượng thuộc các lớp khác nhau một cách thống nhất.
Mở rộng chương trình: Dễ dàng thêm các lớp mới mà không cần sửa đổi code đã có.
Khả năng tái sử dụng: Code có thể được tái sử dụng trong nhiều ngữ cảnh khác nhau.
Tính Trừu Tượng (Abstraction)

Khái niệm
Tính trừu tượng là quá trình ẩn đi các chi tiết phức tạp bên trong và chỉ hiển thị các thông tin cần thiết cho người dùng. Nó cho phép tập trung vào những gì một đối tượng làm thay vì làm như thế nào. Tính trừu tượng giúp giảm độ phức tạp của hệ thống và làm cho code dễ hiểu và dễ bảo trì hơn.
Cơ chế hoạt động
Tính trừu tượng được thực hiện thông qua các lớp trừu tượng (abstract classes) và interface.
Lớp trừu tượng (Abstract Class): Là một lớp không thể tạo ra đối tượng trực tiếp. Nó có thể chứa các phương thức trừu tượng (abstract methods) và các phương thức không trừu tượng (concrete methods). Các phương thức trừu tượng là các phương thức không có phần triển khai, mà chỉ có phần khai báo. Các lớp con phải triển khai (implement) các phương thức trừu tượng này.
Interface: Là một bản thiết kế hoàn toàn trừu tượng, chỉ chứa các phương thức trừu tượng (và các hằng số). Một lớp có thể triển khai (implement) nhiều interface.
Ưu điểm của tính trừu tượng
Giảm độ phức tạp: Che giấu các chi tiết không cần thiết, giúp code dễ hiểu và dễ bảo trì hơn.
Tính linh hoạt: Dễ dàng thay đổi phần triển khai bên trong mà không ảnh hưởng đến các phần khác của chương trình.
Khả năng tái sử dụng: Các lớp trừu tượng và interface có thể được tái sử dụng trong nhiều ứng dụng khác nhau.
