Các tính chất của OOP trong Ruby
Ruby là một ngôn ngữ lập trình hướng đối tượng thuần túy (Pure Object-Oriented Language). Điều này có nghĩa là hầu hết mọi thứ trong Ruby—từ số nguyên, chuỗi cho đến các mảng—đều là đối tượng (Object).
Để làm chủ Ruby, việc hiểu rõ 4 tính chất của OOP là điều bắt buộc.
1. Thành phần cốt lõi: Class và Object
Trước khi đi sâu vào các tính chất, chúng ta cần phân biệt rõ hai khái niệm nền tảng:
- Class (Lớp): Được coi là một "bản thiết kế" (blueprint). Nó định nghĩa các thuộc tính (dữ liệu) và phương thức (hành vi) mà các đối tượng thuộc lớp đó sẽ có.
- Object (Đối tượng): Là một "thực thể" cụ thể được tạo ra từ bản thiết kế (Class). Mỗi đối tượng có trạng thái riêng nhưng chia sẻ cấu trúc chung của lớp.
2. Bốn tính chất vàng của OOP trong Ruby
2.1. Tính kế thừa (Inheritance)
Tính kế thừa cho phép một lớp (lớp con - subclass) thừa hưởng các thuộc tính và phương thức từ một lớp khác (lớp cha - superclass). Điều này giúp tái sử dụng mã nguồn và tạo ra cấu trúc phân cấp logic.
- Cú pháp: Sử dụng ký tự
<.
class Animal
def speak
"Hello!"
end
end
class Cat < Animal
def speak
"Meow meow!"
end
end
cat = Cat.new
puts cat.speak # Kết quả: Meow meow!
2.2. Tính đóng gói (Encapsulation)
Tính đóng gói giúp che giấu thông tin bên trong và chỉ để lộ ra những gì cần thiết thông qua các giao diện công khai. Trong Ruby, chúng ta kiểm soát quyền truy cập bằng 3 từ khóa:
- Public: Có thể truy cập từ bất cứ đâu.
- Protected: Chỉ có thể truy cập bởi các đối tượng trong cùng lớp hoặc các lớp con.
- Private: Chỉ có thể truy cập bên trong chính đối tượng đó (không thể gọi với một receiver cụ thể).
class BankAccount
def initialize(balance)
@balance = balance
end
def display_balance # Public
puts "Số dư của bạn là: #{show_private_balance}"
end
private
def show_private_balance # Private
@balance
end
end
2.3. Tính đa hình (Polymorphism)
Tính đa hình cho phép các đối tượng khác nhau phản hồi cùng một tên phương thức theo những cách khác nhau.
- Overriding (Ghi đè): Lớp con định nghĩa lại một phương thức đã có ở lớp cha để phù hợp với đặc thù của nó.
- Overloading (Nạp chồng): Lưu ý: Ruby không hỗ trợ Overloading theo cách truyền thống (cùng tên phương thức, khác tham số) như Java hay C++. Tuy nhiên, chúng ta có thể giả lập bằng cách sử dụng tham số mặc định hoặc
*args.
# Ví dụ về Duck Typing - một dạng đa hình đặc trưng của Ruby
def make_it_speak(animal)
puts animal.speak
end
# Dù là chó hay mèo, miễn là có phương thức 'speak', chương trình vẫn chạy đúng.
2.4. Tính trừu tượng (Abstraction)
Tính trừu tượng giúp tập trung vào "đối tượng làm gì" thay vì "đối tượng làm điều đó như thế nào". Nó giúp giảm bớt sự phức tạp bằng cách ẩn đi các chi tiết cài đặt bên trong.
Trong Ruby, chúng ta thường thực hiện tính trừu tượng thông qua:
- Modules: Dùng để gom nhóm các phương thức chung (Mixins).
- Thiết kế hệ thống: Chỉ cung cấp các phương thức công khai (API) đơn giản để người dùng tương tác, còn logic xử lý phức tạp được ẩn bên trong các phương thức
private.
3. Tổng quát và lời khuyên
Việc áp dụng tốt OOP trong Ruby không chỉ giúp code của bạn DRY (Don't Repeat Yourself) mà còn giúp hệ thống dễ bảo trì và mở rộng hơn rất nhiều.
Mẹo nhỏ: Đừng cố gắng nhồi nhét quá nhiều logic vào một Class. Hãy tận dụng Module để chia sẻ hành vi giữa các lớp không có quan hệ kế thừa trực tiếp.
Happy Coding! 🚀
All rights reserved