Các lớp học là trụ cột của lập trình hướng đối tượng . OOP rất quan tâm đến tổ chức mã, tái sử dụng và đóng gói.
Đầu tiên, từ chối trách nhiệm: OOP trái ngược một phần với Lập trình hàm , đây là một mô hình khác được sử dụng rất nhiều trong Python. Không phải ai lập trình bằng Python (hoặc chắc chắn là hầu hết các ngôn ngữ) đều sử dụng OOP. Bạn có thể làm rất nhiều thứ trong Java 8 không hướng đối tượng. Nếu bạn không muốn sử dụng OOP, thì đừng. Nếu bạn chỉ viết các tập lệnh một lần để xử lý dữ liệu mà bạn sẽ không bao giờ sử dụng lại, thì hãy tiếp tục viết theo cách của bạn.
Tuy nhiên, có rất nhiều lý do để sử dụng OOP.
Một số lý do:
Tổ chức: OOP định nghĩa các cách mô tả và tiêu chuẩn nổi tiếng và xác định cả dữ liệu và thủ tục trong mã. Cả dữ liệu và thủ tục có thể được lưu trữ ở các mức định nghĩa khác nhau (trong các lớp khác nhau) và có những cách tiêu chuẩn để nói về các định nghĩa này. Đó là, nếu bạn sử dụng OOP theo cách tiêu chuẩn, nó sẽ giúp bản thân sau này của bạn và những người khác hiểu, chỉnh sửa và sử dụng mã của bạn. Ngoài ra, thay vì sử dụng một cơ chế lưu trữ dữ liệu phức tạp, tùy ý (dicts dicts hoặc list hoặc dicts hoặc list of dicts of sets, or any), bạn có thể đặt tên cho các phần của cấu trúc dữ liệu và thuận tiện tham khảo chúng.
Trạng thái: OOP giúp bạn xác định và theo dõi trạng thái. Chẳng hạn, trong một ví dụ cổ điển, nếu bạn đang tạo một chương trình xử lý học sinh (ví dụ: chương trình lớp), bạn có thể giữ tất cả thông tin bạn cần về họ tại một điểm (tên, tuổi, giới tính, cấp lớp, các khóa học, lớp, giáo viên, đồng nghiệp, chế độ ăn uống, nhu cầu đặc biệt, v.v.) và dữ liệu này được duy trì miễn là đối tượng còn sống và có thể dễ dàng truy cập.
Đóng gói : Với đóng gói, thủ tục và dữ liệu được lưu trữ cùng nhau. Các phương thức (thuật ngữ OOP cho các hàm) được xác định ngay bên cạnh dữ liệu mà chúng hoạt động và tạo ra. Trong một ngôn ngữ như Java cho phép kiểm soát truy cập hoặc bằng Python, tùy thuộc vào cách bạn mô tả API công khai của mình, điều này có nghĩa là các phương thức và dữ liệu có thể bị ẩn khỏi người dùng. Điều này có nghĩa là nếu bạn cần hoặc muốn thay đổi mã, bạn có thể làm bất cứ điều gì bạn muốn để triển khai mã, nhưng vẫn giữ các API công khai như cũ.
Kế thừa : Kế thừa cho phép bạn xác định dữ liệu và thủ tục ở một nơi (trong một lớp), sau đó ghi đè hoặc mở rộng chức năng đó sau. Chẳng hạn, trong Python, tôi thường thấy mọi người tạo các lớp con của dict
lớp để thêm chức năng bổ sung. Một thay đổi phổ biến là ghi đè phương thức đưa ra một ngoại lệ khi một khóa được yêu cầu từ một từ điển không tồn tại để đưa ra một giá trị mặc định dựa trên một khóa không xác định. Điều này cho phép bạn mở rộng mã của riêng mình ngay bây giờ hoặc sau này, cho phép người khác mở rộng mã của bạn và cho phép bạn mở rộng mã của người khác.
Khả năng sử dụng lại: Tất cả những lý do này và những lý do khác cho phép khả năng sử dụng lại mã lớn hơn. Mã hướng đối tượng cho phép bạn viết mã solid (đã kiểm tra) một lần, và sau đó sử dụng lại nhiều lần. Nếu bạn cần điều chỉnh một cái gì đó cho trường hợp sử dụng cụ thể của mình, bạn có thể kế thừa từ một lớp hiện có và ghi đè lên hành vi hiện có. Nếu bạn cần thay đổi một cái gì đó, bạn có thể thay đổi tất cả trong khi duy trì chữ ký phương thức công khai hiện có, và không ai là người khôn ngoan hơn (hy vọng).
Một lần nữa, có một số lý do không sử dụng OOP và bạn không cần phải làm vậy. Nhưng may mắn thay với một ngôn ngữ như Python, bạn có thể sử dụng chỉ một chút hoặc rất nhiều, tùy bạn.
Một ví dụ về trường hợp sử dụng của sinh viên (không đảm bảo về chất lượng mã, chỉ là một ví dụ):
Hướng đối tượng
class Student(object):
def __init__(self, name, age, gender, level, grades=None):
self.name = name
self.age = age
self.gender = gender
self.level = level
self.grades = grades or {}
def setGrade(self, course, grade):
self.grades[course] = grade
def getGrade(self, course):
return self.grades[course]
def getGPA(self):
return sum(self.grades.values())/len(self.grades)
# Define some students
john = Student("John", 12, "male", 6, {"math":3.3})
jane = Student("Jane", 12, "female", 6, {"math":3.5})
# Now we can get to the grades easily
print(john.getGPA())
print(jane.getGPA())
Tiêu chuẩn Dict
def calculateGPA(gradeDict):
return sum(gradeDict.values())/len(gradeDict)
students = {}
# We can set the keys to variables so we might minimize typos
name, age, gender, level, grades = "name", "age", "gender", "level", "grades"
john, jane = "john", "jane"
math = "math"
students[john] = {}
students[john][age] = 12
students[john][gender] = "male"
students[john][level] = 6
students[john][grades] = {math:3.3}
students[jane] = {}
students[jane][age] = 12
students[jane][gender] = "female"
students[jane][level] = 6
students[jane][grades] = {math:3.5}
# At this point, we need to remember who the students are and where the grades are stored. Not a huge deal, but avoided by OOP.
print(calculateGPA(students[john][grades]))
print(calculateGPA(students[jane][grades]))