1. Các khái niệm trong OOP
Lập trình hướng đối tượng ‐ Object-oriented programming
- Lập trình hướng đối tượng là một kỹ thuật hỗ trợ, cho phép lập trình viên trực tiếp làm việc với các đối tượng mà họ định nghĩa
- Giúp tăng năng suất, đơn giản hoá độ phức tạp khi bảo trì cũng như mở rộng phần mềm
- Hiện nay có rất nhiều ngôn ngữ lập trình theo hướng đối tượng như C++, Java, PHP,… và Python
- Python là một ngôn ngữ lập trình hướng đối tượng mạnh. Do đó, việc tạo ra và sử dụng các đối tượng là hết sức dễ dàng
Lập trình hướng cấu trúc khác với Lập trình hướng đối tượng
Biến thành viên (Data member)
- Biến được định nghĩa trong lớp hoặc trong đối tượng, thể hiện thuộc tính của đối tượng
Phương thức (Method)
- Hàm được định nghĩa trong lớp nhằm thực hiện một công việc nào đó
Kế thừa (Inheritace)
- Một tính chất của các ngôn ngữ lập trình hướng đối tượng cho phép các lớp kế thừa, thừa hưởng các đặc trưng của lớp được thừa kế
2. Định nghĩa và sử dụng lớp trong Python
- Trong Python, lệnh class được sử dụng để tạo một lớp mới. Tên của lớp theo ngay sau từ khóa class và được theo sau bởi dấu hai chấm
- Cú pháp định nghĩa lớp:
class className: 'documentation string for class' statement_1 …… statement_n
Ví dụ:
class circle2D: def __init__(self, xC, yC, R): self.xC = xC self.yC = yC self.R = R
class car: wheels = 4 def __init__(self, brandName, model, year): self.brandName = brandName self.model = model self.year = year
class studentEM19: 'Python class student for Engineering Mechanics class intake 2019' stdCount = 0 totalCredit = 129 def __init__(self, name, ID, credit): self.name = name self.ID = ID self.credit = credit studentEM19.stdCount += 1 def displayCount(self): print('Total stds in EM19 is: ', studentEM19.stdCount) def displayStudentInfo(self): print('Name: ', self.name, '; ID: ', self.ID) def numOfCreditRemain(self): num = self.totalCredit - self.credit return num
class studentEM19: 'Python class student for Engineering Mechanics class intake 2019' stdCount = 0 def __init__(self, name, ID): self.name = name self.ID = ID studentEM19.stdCount += 1 def displayCount(self): print('Total stds in EM19 is: ', studentEM19.stdCount) def displayStudentInfo(self): print('Name: ', self.name, '; ID: ', self.ID)
Giải thích
- studentEM19 : tên lớp
- ‘Python class student for Engineering Mechanics class intake 2019’: Phần mô tả cho lớp (không bắt buộc, tương tự như chú thích)
- stdCount: là một biến thuộc tính của class studentEM19 có giá trị được chia sẻ trong tất cả instance của lớp này. Biến này có thể được truy cập dưới dạng studentEM19.stdCount từ bên trong lớp hoặc bên ngoài lớp
- __init__(self, name, ID):
– là một phương thức đặc biệt còn gọi phương thức khởi tạo (constructor) cho class
– Python gọi khi người dùng tạo một instance mới của lớp này
– Phương thức khởi tạo được dùng để thiết lập các thuộc tính của lớp
– Không thể khai báo 2 phương thức __init__ trong cùng 1 class - displayCount(self): phương thức của lớp (trong trường hợp này là hàm xuất biến stdCount của lớp)
- displayStudentInfo(self): phương thức của lớp (trong trường hợp này là hàm xuất các biến thuộc tính của đối tượng)
Tạo và sử dụng đối tượng thuộc lớp
Cú pháp: objectName = className (property1,…,propertyN)
Chú ý: số thuộc tính (property) truyền cho đối tượng bằng số thuộc tính trong định nghĩa lớp
Ví dụ:
# Tạo class class studentEM19: 'Python class student for Engineering Mechanics class intake 2019' stdCount = 0 def __init__(self, name, ID): self.name = name self.ID = ID studentEM19.stdCount += 1 def displayCount(self): print('Total stds in EM19 is: ', studentEM19.stdCount) def displayStudentInfo(self): print('Name: ', self.name, '; ID: ', self.ID)
# Sử dụng class std1 = studentEM19('Lê Văn A’, 19123456) print(std1.__doc__) print(std1.name) print(std1.ID) std1.displayStudentInfo() print(studentEM19.stdCount) std2 = studentEM19('Lê Văn B’, 19123459) std2.displayStudentInfo() std2.displayCount()
# Output: Python class student for Engineering Mechanics class intake 2019 Lê Văn A 16123456 Name: Lê Văn A ; ID: 16123456 1 Name: Lê Văn B ; ID: 16123459 Total stds in EM19 is: 2
- Có thể thêm, xóa, hoặc sửa đổi các thuộc tính của các lớp và đối tượng tại bất cứ thời điểm nào
std1.name = 'Nguyễn Anh C' # Thuộc tính name của std1 đã bị thay đổi thành giá trị mới print(std1.name)
std1.age = 19 # thêm thuộc tính age cho đối tượng std1 print(std1.age)
del std1.age # xóa thuộc tính age của đối tượng std1
std1.gender = 'male' print(std1.gender) # thêm thuộc tính gender cho đối tượng std1
- Ngoài các cách thông thường để truy cập các thuộc tính và phương thức, Python còn cho phép truy cập thông qua một số hàm có sẵn
Hàm | Mô tả |
getattr(obj, name[, default]) | Lấy một thuộc tính nào đó của đối tượng, nếu đối tượng này không có thuộc tính đó thì giá trị trả về là default. Khi default không được truyền vào thì giá trị trả về là None. |
hasattr(obj, name) | Kiểm tra một thuộc tính nào đó có tồn tại trong đối tượng này hay không, nếu có thì trả về True và ngược lại. |
setattr(obj,name,value) | Gán giá trị value cho một thuộc tính trong đối tượng. |
delattr(obj, name) | Xoá thuộc tính trong đối tượng. |
Các thuộc tính đã có sẵn cho lớp trong Python
Mỗi lớp Python đều có các thuộc tính đã được xây dựng sẵn, có thể được truy cập như bất kỳ thuộc tính khác
- __dict__: Là Dictionary chứa namespace của lớp.
- __doc__: Được sử dụng để truy cập Documentation String của lớp nếu có.
- __name__: Là tên lớp.
- __module__: Là tên Module trong đó lớp được định nghĩa. Thuộc tính là __main__ trong chế độ tương tác
- __bases__: Là một Tuple chứa các lớp cơ sở
3. Lớp kế thừa
- Kế thừa trong lập trình được hiểu đơn giản là sự thừa hưởng, thừa kế các thuộc tính, phương thức từ lớp cha (lớp được kế thừa) và được quyền sử dụng chúng như là của chính bản thân mình (lớp kế thừa)
- Một lớp con cũng có thể ghi đè các thành viên dữ liệu và các phương thức từ lớp cha
- Kế thừa giúp người lập trình tiết kiệm thời gian để viết code, dễ dàng bảo trì và mở rộng
- Trong Python có 2 loại kế thừa là đơn kế thừa và đa kế thừa
Cú pháp:
class childClass(parentClass1[, parentClass2, ...]): statement1 . . statementN
Ví dụ:
class Animal: def __init__(self, genus, age): self.genus = genus self.age = age def say(self): pass class Duck(Animal): def __init__(self): Animal.__init__(self, ‘Duck’, 2) def say(self): print("Quack quack!")
# Lớp Duck được khai báo kế thừa từ lớp Animal # Phương thức __init__ được override từ phương thức __init__ ở lớp cha # Phương thức say được override lại từ phương thức say ở lớp cha
Một số tính chất cần lưu ý
- Khi phương thức __init__ ở lớp con không được khai báo, nó sẽ dùng phương thức __init__ ở lớp cha
- Khác với các C++, trong Python chỉ có một loại kế thừa duy nhất là public
- Trong Python các thuộc tính, phương thức của lớp không tồn tại khái niệm protected như ở C++ mà chỉ tồn tại ở dạng private và public và chúng được phân biệt dựa theo tên
– Kiểu private: Tên được bắt đầu bằng 2 dấu gạch dưới “__” và kết thúc tối đa là 1 dấu gạch dưới. (Ví dụ: __abc, __xyz_, …)
– Kiểu public: Tất cả các tên không phải tên của kiểu private và đúng quy tắc đều thuộc kiểu public
Ví dụ:
# Tạo class class Animal: def __init__(self, genus, age): self.genus = genus self.age = age def say(self): pass def __leg__(self): if self.genus == 'Duck': return 2 elif self.genus == 'Dog': return 4 class Duck(Animal): def __init__(self): Animal.__init__(self, 'Duck', 1) def say(self): print("Quack quack!") # Sử dụng class duck = Duck() print(duck.genus) print(duck.age) duck.say() print(duck.__leg__()) # Kết quả Duck 1 Quack quack! 2
# Tạo class class Animal: def __init__(self, genus, age): self.genus = genus self.age = age def say(self): pass def __leg(self): if self.genus == 'Duck': return 2 elif self.genus == 'Dog': return 4 # Sử dụng class class Dog(Animal): def say(self): print("Gau Gau!") # Kết quả: dog1 = Dog('Dog',2) print(dog1.genus) print(dog1.age) dog1.say() print(dog1.__leg())
Các dạng kế thừa trong Python
- Đơn thừa kế (Single Inheritance)
- Đa thừa kế (Multiple Inheritance)
- Thừa kế đa tầng (Multilevel Inheritance)
- Thừa kế thứ bậc (Hierarchical Inheritance)
- Thừa kế hỗn hợp (Hibrid Inheritance)