🌱 [Python] 17 - OOP Concepts: Class and Object
Class và Object là hai khái niệm trung tâm trong lập trình hướng đối tượng (OOP). Bài viết này sẽ cùng mọi người tìm hiểu về hai khái niệm quan trọng này và cách sử dụng chúng trong ngôn ngữ lập trình Python.
1 - Giới thiệu về Class và Object
Class và Object là hai khái niệm trung tâm trong lập trình hướng đối tượng (OOP). - Class là bản thiết kế (blueprint) mô tả cấu trúc và hành vi (attributes và methods) của đối tượng. Object là thể hiện cụ thể (instance) được tạo ra từ class.
Class
Class định nghĩa cấu trúc và hành vi của các đối tượng bằng cách đóng gói dữ liệu (thuộc tính) và phương thức (hàm). Bản thân class không chiếm bộ nhớ cho đến khi một object được khởi tạo từ class đó.
Bạn có thể định nghĩa class trong Python bằng từ khóa class
. Mỗi class có thể bao gồm:
- Thuộc tính (attributes): lưu trữ dữ liệu hoặc trạng thái của đối tượng.
- Phương thức (methods): định nghĩa hành vi của đối tượng.
Ví dụ: class Car có thể định nghĩa các thuộc tính như màu sắc và tốc độ, cũng như các phương thức như drive() hoặc stop().
class Car:
def __init__(self, color, speed):
self.color = color
self.speed = speed
def drive(self):
print(f"The {self.color} car is driving at {self.speed} km/h.")
Object
Object - Đối tượng là một thể hiện cụ thể của một class. Nó đại diện cho một thực thể cụ thể với dữ liệu và hành vi riêng biệt, được định nghĩa bởi class. Khi một object được tạo, bộ nhớ được cấp phát để lưu trữ dữ liệu của nó.
↪ Khi bạn gọi class như một hàm, Python sẽ tự động tạo ra một object.
Ví dụ: my_car = Car("red", 100) tạo ra một object với tên my_car với các thuộc tính cụ thể.
# Creating objects from the Car class
my_car = Car("red", 100)
your_car = Car("blue", 120)
# Accessing methods and attributes
my_car.drive() # Output: The red car is driving at 100 km/h
your_car.drive() # Output: The blue car is driving at 120 km/h
2 - Phương thức khởi tạo (__init__)
Hàm đặc biệt __init__()
được gọi tự động khi một object được tạo.
Nó giúp khởi tạo các giá trị mặc định cho object.
class Car:
def __init__(self, brand, model):
self.brand = brand
self.model = model
my_car = Car("Toyota", "Camry")
print(my_car.brand) # Toyota
3 - Từ khóa self và ý nghĩa
Từ khóa self
đại diện cho chính object hiện tại.
Python sử dụng self
để truy cập các thuộc tính và phương thức của object đó.
class Car:
def __init__(self, brand, model):
self.brand = brand
self.model = model
def get_model(self):
print(f"Model: {self.model}")
my_car = Car("Toyota", "Camry")
my_car.get_model() # Camry
4 - Phương thức của class
Phương thức (method) là các hàm được định nghĩa trong class để mô tả hành vi của đối tượng. Bạn có thể phân loại:
- Instance method: hoạt động trên từng đối tượng, sẽ bắt buộc có một tham số là self.
- Class method: hoạt động ở mức class, dùng decorator
@classmethod
. - Static method: không phụ thuộc vào class hay instance, dùng
@staticmethod
.
class Example:
counter = 0
def __init__(self):
Example.counter += 1
@classmethod
def get_count(cls):
return cls.counter
@staticmethod
def info():
print("This is a static method.")
e1 = Example()
e2 = Example()
print(Example.get_count()) # 2
Example.info()
Các Instance method cũng có thể gọi lần nhau bằng cách sử dụng từ khóa self.
class Car:
def __init__(self, brand, model):
self.brand = brand
self.model = model
self.speed = 0
def get_model(self):
print(f"Model: {self.model}")
def start_engine(self):
print(f"{self.brand} {self.model} engine started.")
# Gọi method khác qua self
self.show_status()
def accelerate(self, amount):
self.speed += amount
print(f"{self.brand} {self.model} is now at {self.speed} km/h.")
# Gọi method khác trong cùng class
self.show_status()
def show_status(self):
print(f"→ Current speed: {self.speed} km/h")
my_car = Car("Toyota", "Camry")
my_car.start_engine() # start_engine gọi self.show_status()
my_car.accelerate(50) # accelerate gọi self.show_status()
5 - Thuộc tính của đối tượng
Thuộc tính có thể được truy cập và thay đổi trong runtime.
Bạn có thể dùng hasattr()
, getattr()
, setattr()
, và delattr()
để thao tác động.
- class Car:
- def __init__(self, brand, model):
- self.brand = brand
- self.model = model
- self.speed = 0
- def get_model(self):
- print(f"Model: {self.model}")
- def accelerate(self, amount):
- self.speed += amount
- print(f"{self.brand} {self.model} is now running at {self.speed} km/h.")
- # --- Tạo object ---
- my_car = Car("Toyota", "Camry")
- # --- 1️⃣ Kiểm tra xem thuộc tính có tồn tại không ---
- if hasattr(my_car, "brand"):
- print("✅ Attribute 'brand' exists:", my_car.brand)
- else:
- print("❌ Attribute 'brand' does not exist")
- # --- 2️⃣ Lấy giá trị thuộc tính bằng getattr() ---
- model_name = getattr(my_car, "model", "Unknown")
- print("🚗 Model:", model_name)
- # --- 3️⃣ Gán thêm một thuộc tính mới bằng setattr() ---
- setattr(my_car, "color", "White")
- print("🎨 Added attribute 'color':", my_car.color)
- # --- 4️⃣ Gọi method động bằng getattr() ---
- method = getattr(my_car, "accelerate", None)
- if callable(method):
- method(40) # Gọi method accelerate(40)
- # --- 5️⃣ Xóa thuộc tính bằng delattr() ---
- if hasattr(my_car, "color"):
- delattr(my_car, "color")
- print("🧽 Attribute 'color' deleted.")
- # --- 6️⃣ Thử truy cập lại thuộc tính đã xóa ---
- print("Color exists?", hasattr(my_car, "color"))
6. Một số khái niệm quan trọng
Getter and Setter Methods
Getter và Setter cung cấp cách truy cập có kiểm soát đến thuộc tính của đối tượng.
Chúng giúp đóng gói dữ liệu (encapsulation) và ngăn việc thay đổi trực tiếp các biến nội bộ.
Trong Python, ta dùng @property
và @<property>.setter
để cài đặt getter và setter.
- class Car:
- def __init__(self, brand, model):
- self._brand = brand # Dấu gạch dưới _ cho biết thuộc tính là "private"
- self._model = model
- # Getter cho brand
- @property
- def brand(self):
- print("Getting brand...")
- return self._brand
- # Setter cho brand
- @brand.setter
- def brand(self, value):
- print("Setting brand...")
- if not isinstance(value, str):
- raise ValueError("Brand must be a string.")
- self._brand = value
- # Getter cho model
- @property
- def model(self):
- return self._model
- # Setter cho model
- @model.setter
- def model(self, value):
- if len(value) < 2:
- raise ValueError("Model name is too short.")
- self._model = value
- # --- Sử dụng ---
- my_car = Car("Toyota", "Camry")
- print(my_car.brand) # Tự động gọi getter
- my_car.brand = "Honda" # Tự động gọi setter
- print(my_car.brand)
- # Thử setter lỗi
- try:
- my_car.brand = 123 # Không hợp lệ
- except ValueError as e:
- print("Error:", e)
💡 Giải thích:
- __init__: Hàm khởi tạo của class, tạo hai thuộc tính private là _brand và _model. Dấu gạch dưới (_) thể hiện rằng các thuộc tính này không nên truy cập trực tiếp từ bên ngoài class.
- @property: Dùng để định nghĩa getter cho thuộc tính brand. Khi gọi my_car.brand, Python tự động gọi hàm brand(self) thay vì truy cập trực tiếp _brand.
- @brand.setter: Dùng để định nghĩa setter cho thuộc tính brand. Khi gán my_car.brand = "Honda", Python sẽ gọi brand(self, value) để kiểm tra và cập nhật giá trị. Trong ví dụ, setter kiểm tra kiểu dữ liệu phải là str, nếu không sẽ raise ValueError.
- @property (cho model): Định nghĩa getter cho model, cho phép đọc my_car.model mà không cần gọi hàm.
- @model.setter: Định nghĩa setter cho model. Setter kiểm tra độ dài của chuỗi, nếu nhỏ hơn 2 ký tự sẽ raise lỗi ValueError("Model name is too short.").
- self._brand và self._model: Là các biến nội bộ (private) thực sự lưu trữ dữ liệu của object. Getter và setter hoạt động như “cửa kiểm soát” truy cập đến các biến này.
Method Overriding
Method Overriding (ghi đè phương thức) xảy ra khi subclass định nghĩa lại một phương thức đã có trong superclass. Điều này cho phép mở rộng hoặc thay đổi hành vi kế thừa.
- class Car:
- def __init__(self, brand, model):
- self.brand = brand
- self.model = model
- def start_engine(self):
- print(f"{self.brand} {self.model}: Engine started with a key.")
- # Class con kế thừa từ Car
- class ElectricCar(Car):
- def __init__(self, brand, model, battery_capacity):
- super().__init__(brand, model)
- self.battery_capacity = battery_capacity
- # 🔁 Overriding method từ class cha
- def start_engine(self):
- print(f"{self.brand} {self.model}: Powering on silently (battery: {self.battery_capacity} kWh).")
- # --- Sử dụng ---
- car1 = Car("Toyota", "Camry")
- car2 = ElectricCar("Tesla", "Model 3", 75)
- car1.start_engine() # Gọi method của class Car
- car2.start_engine() # Gọi method bị ghi đè trong class ElectricCar
Trong đoạn code trên, class Car là class cha, định nghĩa phương thức start_engine() — giả lập xe dùng động cơ xăng. class ElectricCar(Car) là class con, kế thừa tất cả thuộc tính và phương thức của Car.
Dòng super().__init__(brand, model) gọi hàm khởi tạo của class cha để tránh lặp code.
- def start_engine(self): (trong ElectricCar): Đây là method overriding.
Class ElectricCar định nghĩa lại phương thức start_engine() có cùng tên với class Car, nhưng hành vi khác (không dùng chìa, mà dùng pin).
Khi gọi car2.start_engine(), Python ưu tiên method trong class con → method của Car bị ghi đè. Nếu vẫn muốn gọi method của class cha, có thể dùng trong class con.
super().start_engine()
Static Methods và Class Methods
Cả hai loại phương thức này đều gắn với class thay vì instance:
- Static Method: không truy cập instance hay class, dùng
@staticmethod
. - Class Method: truy cập class thông qua tham số
cls
, dùng@classmethod
.
- class Car:
- total_cars = 0 # Thuộc tính class (dùng chung cho tất cả đối tượng)
- def __init__(self, brand, model):
- self.brand = brand
- self.model = model
- Car.total_cars += 1
- @staticmethod
- def general_info():
- """Static Method: Không truy cập self hoặc cls"""
- print("Cars are vehicles used for transportation.")
- @classmethod
- def show_total_cars(cls):
- """Class Method: Làm việc với thuộc tính class"""
- print(f"Total cars created: {cls.total_cars}")
- # Sử dụng
- car1 = Car("Toyota", "Camry")
- car2 = Car("Honda", "Civic")
- Car.general_info() # Static method
- Car.show_total_cars() # Class method
Abstract Classes và Interfaces
Abstract Class cung cấp "mẫu" cho các lớp con kế thừa, ép buộc chúng phải cài đặt các phương thức nhất định.
Python sử dụng module abc
để định nghĩa lớp trừu tượng (abstract class).
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def sound(self):
pass
class Dog(Animal):
def sound(self):
print("Woof")
dog = Dog()
dog.sound() # Woof
Giải thích:
ABC
: class cơ sở cho mọi abstract class.@abstractmethod
: khai báo phương thức phải được override.Dog
triển khai lạisound()
— nếu không, Python sẽ báo lỗi khi tạo instance.
Class Variables vs Instance Variables
Phân biệt rõ giữa:
- Class Variable: dùng chung cho mọi instance.
- Instance Variable: riêng biệt cho từng đối tượng.
class Dog:
species = "Canine" # Class variable
def __init__(self, name, age):
self.name = name # Instance variable
self.age = age
dog1 = Dog("Buddy", 3)
dog2 = Dog("Lucy", 2)
print(dog1.species) # Canine
print(dog2.name) # Lucy
Giải thích:
species
: chia sẻ giữa mọi đối tượngDog
.name
,age
: giá trị riêng của từng instance.dog1.species
vàdog2.name
minh họa sự khác biệt rõ ràng.
7 - Tổng kết
Khái niệm | Ý nghĩa | Ví dụ |
---|---|---|
Class | Bản thiết kế cho các object | class Dog: |
Object | Thể hiện cụ thể của class | dog1 = Dog() |
__init__() | Hàm khởi tạo đối tượng | def __init__(...) |
self | Tham chiếu chính đối tượng hiện tại | self.name = ... |
Phương thức | Hành vi của đối tượng | def bark(self): |
>>>>>> Follow ngay <<<<<<<
Để nhận được những bài học miễn phí mới nhất nhé 😊
Chúc các bạn học tập tốt 😊