Giới Thiệu Lập Trình Hướng Đối Tượng trong Python: Lớp và Đối Tượng

Giới Thiệu 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ẽ, giúp tổ chức mã nguồn một cách rõ ràng và hiệu quả hơn so với các phương pháp lập trình thủ tục hoặc hàm truyền thống. Trong lập trình thủ tục, mã nguồn thường lặp lại và khó quản lý khi dự án phát triển. OOP khắc phục điều này bằng cách nhóm các thuộc tính và hành vi có liên quan vào các thực thể được gọi là "đối tượng", mang lại khả năng tái sử dụng và dễ bảo trì cao.

Khái Niệm Cơ Bản: Lớp và Đối Tượng

  • Lớp (Class): Là một bản thiết kế (blueprint) hoặc khuôn mẫu để tạo ra các đối tượng. Nó định nghĩa các thuộc tính (dữ liệu) và phương thức (hành vi) chung mà tất cả các đối tượng được tạo từ lớp đó sẽ có. Ví dụ, một lớp Car có thể định nghĩa rằng mọi chiếc xe đều có brand (hãng sản xuất) và có thể start_engine (khởi động động cơ) hay drive (lái).
  • Đối tượng (Object): Là một thể hiện cụ thể (instance) của một lớp. Khi bạn tạo một đối tượng từ một lớp, nó sẽ có các thuộc tính và phương thức được định nghĩa trong lớp đó, nhưng với các giá trị riêng biệt. Ví dụ, từ lớp Car, bạn có thể tạo ra một đối tượng my_car màu đỏ của hãng Toyota, hoặc một đối tượng your_car màu xanh của hãng Honda.

Định Nghĩa Lớp và Thuộc Tính Lớp (Class Attributes)

Trong Python, bạn định nghĩa một lớp bằng từ khóa class. Thuộc tính lớp (hay thuộc tính tĩnh) là những thuộc tính được chia sẻ bởi tất cả các thể hiện của lớp. Chúng được định nghĩa trực tiếp bên trong khối class nhưng bên ngoài bất kỳ phương thức nào.

class Vehicle:
    # Thuộc tính lớp (class attributes): chung cho tất cả các đối tượng Vehicle
    global_origin = "Worldwide"
    default_wheel_count = 4

    def describe_vehicle(self):
        print(f"Đây là một phương tiện có nguồn gốc từ {self.global_origin} với {self.default_wheel_count} bánh.")

# Truy cập thuộc tính lớp thông qua tên lớp
print(f"Nguồn gốc toàn cầu mặc định: {Vehicle.global_origin}")
print(f"Số bánh xe mặc định: {Vehicle.default_wheel_count}")

Bạn có thể xem tất cả các thuộc tính của một lớp bằng cách sử dụng Class.__dict__. Điều này cho thấy cả thuộc tính lớp và các phương thức được định nghĩa.

print(Vehicle.__dict__)
# Kết quả sẽ bao gồm 'global_origin', 'default_wheel_count', 'describe_vehicle', và các thuộc tính nội bộ khác.

Thao tác với Thuộc Tính Lớp (Thông qua tên lớp):

Bạn có thể thêm, xóa, sửa, hoặc truy vấn thuộc tính lớp bằng cách sử dụng tên lớp:

# Thêm một thuộc tính lớp mới
Vehicle.category = "Land Transport"
print(f"Loại phương tiện: {Vehicle.category}")

# Sửa một thuộc tính lớp
Vehicle.global_origin = "Europe"
print(f"Nguồn gốc toàn cầu đã cập nhật: {Vehicle.global_origin}")

# Xóa một thuộc tính lớp
del Vehicle.default_wheel_count
print(Vehicle.__dict__) # 'default_wheel_count' không còn trong dictionary
# print(Vehicle.default_wheel_count) # Sẽ gây ra AttributeError

Tuy nhiên, việc thao tác trực tiếp với __dict__ không được khuyến khích cho các hoạt động thông thường; thay vào đó, hãy sử dụng cú pháp dấu chấm (.).

Tạo Đối Tượng (Instantiation) và Phương Thức Khởi Tạo __init__

Để tạo một đối tượng từ một lớp, bạn gọi tên lớp như một hàm (ví dụ: Car()). Quá trình này được gọi là khởi tạo (instantiation). Khi một đối tượng được tạo, một phương thức đặc biệt tên là __init__ (nếu được định nghĩa) sẽ được tự động gọi. __init__ đóng vai trò là hàm tạo (constructor) của lớp, dùng để khởi tạo trạng thái ban đầu của đối tượng bằng cách gán các giá trị cho các thuộc tính riêng của nó (thuộc tính đối tượng hoặc thuộc tính thể hiện).

Tham số đầu tiên của mọi phương thức trong một lớp, bao gồm __init__, luôn là self. self là một tham chiếu đến chính đối tượng đang được tạo hoặc đang gọi phương thức đó.

class Car:
    # Thuộc tính lớp
    vehicle_type = "Passenger Car"

    def __init__(self, brand_name, model_year):
        # 'self' ở đây tham chiếu đến đối tượng 'Car' mới được tạo.
        # Các thuộc tính này là thuộc tính đối tượng (instance attributes)
        # Chúng là duy nhất cho mỗi đối tượng Car.
        self.brand = brand_name
        self.year = model_year
        print(f"Một chiếc xe {self.brand} đời {self.year} đã được tạo.")

    def show_details(self):
        # Phương thức của đối tượng
        print(f"Đây là một chiếc {self.vehicle_type} nhãn hiệu {self.brand}, sản xuất năm {self.year}.")

# Tạo đối tượng (khởi tạo)
my_sedan = Car("Toyota", 2020)
my_suv = Car("Honda", 2022)

print("\n--- Chi tiết các đối tượng ---")
my_sedan.show_details()
my_suv.show_details()

Thuộc Tính Đối Tượng (Instance Attributes)

Các thuộc tính được định nghĩa bên trong __init__ (sử dụng self.attribute_name) là thuộc tính của đối tượng. Mỗi đối tượng sẽ có một bộ các thuộc tính này với các giá trị riêng biệt.

Bạn có thể truy cập và thao tác với các thuộc tính đối tượng bằng cách sử dụng cú pháp dấu chấm với tên đối tượng:

print(f"Xe sedan của tôi là hãng: {my_sedan.brand}")
my_sedan.brand = "Ford" # Sửa thuộc tính đối tượng
print(f"Xe sedan của tôi sau khi đổi hãng: {my_sedan.brand}")

# Thêm một thuộc tính mới cho riêng đối tượng 'my_sedan'
my_sedan.color = "Red"
print(f"Màu xe sedan của tôi: {my_sedan.color}")

# 'my_suv' không có thuộc tính 'color' này (trừ khi nó được thêm riêng)
# print(my_suv.color) # Sẽ gây ra lỗi AttributeError nếu truy cập

Thao tác với Thuộc Tính Đối Tượng:

  • Thêm: obj.new_attribute = value
  • Xóa: del obj.attribute_name
  • Sửa: obj.attribute_name = new_value
  • Truy vấn: print(obj.attribute_name)

Quan Hệ Giữa Đối Tượng và Thuộc Tính Lớp/Phương Thức

Một đối tượng có thể truy cập các thuộc tính lớp và các phương thức của lớp. Khi một đối tượng truy cập một thuộc tính lớp, nó thực chất đang truy cập vào phiên bản chung của thuộc tính đó. Tuy nhiên, nếu bạn cố gắng "sửa đổi" một thuộc tính lớp thông qua một đối tượng, Python sẽ tạo một thuộc tính đối tượng mới cùng tên trên đối tượng đó, thay vì thay đổi thuộc tính lớp chung.

class Gadget:
    # Thuộc tính lớp
    power_source = "Battery"
    warranty_period = "1 Year"

    def __init__(self, serial_id):
        self.id = serial_id

# Tạo hai đối tượng
device1 = Gadget("GX001")
device2 = Gadget("GY002")

# Truy cập thuộc tính lớp qua đối tượng
print(f"Thiết bị 1 dùng nguồn: {device1.power_source}, Bảo hành: {device1.warranty_period}")
print(f"Thiết bị 2 dùng nguồn: {device2.power_source}, Bảo hành: {device2.warranty_period}")

# Thay đổi thuộc tính lớp qua TÊN LỚP
Gadget.power_source = "USB-C"
print(f"\n--- Sau khi thay đổi nguồn cấp qua LỚP ---")
print(f"Thiết bị 1 dùng nguồn mới: {device1.power_source}") # Output: USB-C
print(f"Thiết bị 2 dùng nguồn mới: {device2.power_source}") # Output: USB-C

# Thay đổi thuộc tính (tạo thuộc tính đối tượng) qua ĐỐI TƯỢNG
device1.power_source = "Solar" # Điều này tạo ra một thuộc tính 'power_source' riêng cho device1
print(f"\n--- Sau khi thay đổi nguồn cấp qua ĐỐI TƯỢNG device1 ---")
print(f"Thiết bị 1 dùng nguồn độc lập: {device1.power_source}") # Output: Solar
print(f"Thiết bị 2 vẫn dùng nguồn chung: {device2.power_source}") # Output: USB-C (không bị ảnh hưởng)
print(f"Nguồn gốc của lớp Gadget: {Gadget.power_source}") # Output: USB-C (cũng không bị ảnh hưởng bởi device1)

Lớp là một bản thiết kế, định nghĩa cấu trúc và hành vi chung. Đối tượng là một thực thể cụ thể được tạo từ lớp, mang trong mình các giá trị riêng biệt cho các thuộc tính và có khả năng thực hiện các hành vi đã định nghĩa. self là chìa khóa để một đối tượng tương tác với chính dữ liệu và phương thức của nó.

Thẻ: python Lập trình hướng đối tượng oop class object

Đăng vào ngày 25 tháng 7 lúc 17:57