Lập trình hướng đối tượng là 1 cách lập trình cho phép người lập trình nghĩ như thể họ đang làm việc với các thực thể ngoài đời thực hoặc các đối tượng (thực thể hoặc các đối tượng là 1 thứ có sự tồn tại riêng biệt và độc lập). Thì có nghĩa là trong cuộc sống thực, mọi người có kiến thức, kỹ năng…và có thể làm nhiều công việc khác nhau thì trong OOP, các đối tượng có các trường để lưu trữ kiến thức, kỹ năng, trạng thái, dữ liệu… và có các phương thức để thực hiện các công việc khác nhau thông qua 4 tính chất hay còn gọi là tứ trụ của OOP (Four Pillars of OOP) là đóng gói, kế thừa, đa hình, trừu tượng.
1 - Tính đóng gói (Encapsulation)
Định nghĩa
Đóng gói là gói dữ liệu (thuộc tính) và phương thức (hàm) hoạt động trên dữ liệu thành một đơn vị duy nhất được gọi là class. Nó liên quan đến việc hạn chế quyền truy cập vào một số thành phần của đối tượng, thường bằng cách sử dụng các access modifier (ví dụ: public, private...).
Mục đích
Đóng gói giúp bảo vệ tính toàn vẹn của dữ liệu bằng cách kiểm soát quyền truy cập vào dữ liệu đó. Nó ẩn các chi tiết bên trong về cách thức hoạt động của một đối tượng, chỉ hiển thị những gì cần thiết.
Ví dụ
Xem xét một hệ thống ngân hàng. Thông tin về tài khoản như số dư, lịch sử giao dịch không nên được truy cập trực tiếp từ bên ngoài. Thay vào đó, các phương thức như nạp tiền, rút tiền được cung cấp để thực hiện các thao tác một cách an toàn.
class BankAccount {
private double balance;
public void deposit(double amount) {
// Logic để nạp tiền và cập nhật số dư
balance += amount;
}
public void withdraw(double amount) {
// Logic để rút tiền và cập nhật số dư
balance -= amount;
}
public double getBalance() {
return balance;
}
}
Trong ví dụ này, balance
được hạn chế (private
) và chỉ có thể được truy cập thông qua các phương thức public như deposit
, withdraw
, getBalance.
2 - Tính kế thừa (Inheritance)
Định nghĩa
Tính kế thừa cho phép 1 class (subclass hoặc derived class) kế thừa các thuộc tính và hành vi (thuộc tính và phương thức) từ 1 class khác (base class hoặc parent class). Nó thiết lập mối quan hệ " is-a " giữa các class. Đây cũng là tính chất bị hiểu sai và sử dụng sai nhiều nhất trong 4 tính chất.
Mục đích
Tính kế thừa giúp tái sử dụng code, cho phép tạo 1 class mới là phiên bản sửa đổi (modified version) của class hiện có. Nó tạo điều kiện cho sự phát triển của mối quan hệ phân cấp (hierarchical relationships) giữa các class.
Ví dụ
Xem xét object class Shape. Có thể tạo các sub class như Circle và Rectangle kế thừa từ Shape class, chia sẻ các thuộc tính chung như area
và phương thức chung như calculateArea
, tuy nhiên cũng có thể có các thuộc tính và phương thức riêng của chính nó.
class Shape {
// Các thuộc tính và phương thức chung
}
class Circle extends Shape {
// Các thuộc tính và phương thức riêng của hình tròn
}
class Rectangle extends Shape {
// Các thuộc tính và phương thức riêng của hình chữ nhật
}
3 - Tính đa hình (Polymorphism)
Định nghĩa
Tính đa hình cho phép các đối tượng thuộc các loại khác nhau được coi là các đối tượng thuộc 1 loại chung và cho phép 1 đối tượng có thể thể hiện các hành vi khác nhau tùy thuộc vào ngữ cảnh, giúp linh hoạt trong việc sử dụng và mở rộng chức năng.
Nó có thể xảy ra tại thời điểm biên dịch (compile-time polymorphism) thông qua method overloading hoặc trong thời gian chạy (runtime polymorphism) thông qua method overriding.
Mục đích
Tính đa hình tăng cường tính linh hoạt bằng cách cung cấp 1 interface duy nhất để thể hiện các loại đối tượng khác nhau. Nó đơn giản hóa code và cải thiện khả năng đọc (giúp hiểu rõ code 1 cách nhanh chóng và dễ dàng, bao gồm những lập trình viên khác và chính bạn trong tương lai).
Ví dụ
Xem xét 1 ứng dụng về hình học. Cả Circle và Retangle có thể có 1 method draw(), nhưng cách triển khai cụ thể của nó sẽ khác nhau.
interface Shape {
void draw();
}
class Circle implements Shape {
@Override
public void draw() {
// Logic để vẽ hình tròn
}
}
class Rectangle implements Shape {
@Override
public void draw() {
// Logic để vẽ hình chữ nhật
}
}
4 - Tính trừu tượng(Abstraction)
Định nghĩa
Tính trừu tượng liên quan đến việc đơn giản hóa các hệ thống phức tạp bằng cách mô hình hóa các class dựa trên các thuộc tính và hành vi thiết yếu của chúng. Nó thường liên quan đến việc tạo các abstract class hoặc interface xác định cấu trúc chung mà không chỉ định chi tiết triển khai.
Nói 1 cách dễ hiểu hơn tính chất này giúp tạo ra các class và phương thức trừu tượng để che giấu thông tin chi tiết và chỉ hiển thị những điều quan trọng.
Mục đích
Tính trừu tượng làm giảm độ phức tạp bằng cách ẩn các chi tiết không cần thiết và tập trung vào các tính năng thiết yếu. Nó cho phép các developers tạo các khung tổng quát (abstract class, interface) có thể được extend hoặc implement bởi các class cụ thể.
Ví dụ
Xem xét một ứng dụng quản lý sách. Có thể tạo một lớp Book
trừu tượng chứa các thuộc tính chung như title
, author
, và price
, sau đó tạo các lớp con như FictionBook
và NonFictionBook
để thêm các thuộc tính và phương thức cụ thể.
abstract class Book {
private String title;
private String author;
private double price;
// Phương thức trừu tượng
abstract void displayInfo();
}
class FictionBook extends Book {
private String genre;
@Override
void displayInfo() {
// Logic để hiển thị thông tin sách fiction
}
}
class NonFictionBook extends Book {
private String topic;
@Override
void displayInfo() {
// Logic để hiển thị thông tin sách non-fiction
}
}
Tổng kết
Bốn thuộc tính này phối hợp với nhau để cung cấp nền tảng vững chắc cho việc thiết kế các hệ thống phần mềm mô-đun, có thể bảo trì và có thể mở rộng. Giúp code có khả năng tổ chức, khả năng tái sử dụng và khả năng thích ứng với những thay đổi trong quá trình phát triển phần mềm.