Các kiểu kế thừa trong Python W3schools
Trong bài viết này, bạn sẽ khám phá tính kế thừa và thành phần trong Python. Kế thừa và thành phần là hai khái niệm quan trọng trong lập trình hướng đối tượng, mô hình hóa mối quan hệ giữa hai lớp. Chúng là các khối xây dựng của thiết kế hướng đối tượng và chúng giúp các lập trình viên viết mã có thể tái sử dụng Show
Đến cuối bài viết này, bạn sẽ biết cách
Tiền thưởng miễn phí. Nhấp vào đây để có quyền truy cập vào Bảng cheat Python OOP miễn phí chỉ cho bạn các hướng dẫn, video và sách hay nhất để tìm hiểu thêm về Lập trình hướng đối tượng với Python What Are Inheritance and Composition?Inheritance and composition are two major concepts in object oriented programming that model the relationship between two classes. They drive the design of an application and determine how the application should evolve as new features are added or requirements change Both of them enable code reuse, but they do it in different ways Remove adsWhat’s Inheritance?Inheritance models what is called an is a relationship. This means that when you have a 6 class that inherits from a 7 class, you created a relationship where 6 is a specialized version of 7Inheritance is represented using the Unified Modeling Language or UML in the following way Classes are represented as boxes with the class name on top. The inheritance relationship is represented by an arrow from the derived class pointing to the base class. The word extends is usually added to the arrow Note. In an inheritance relationship
Let’s say you have a base class 0 and you derive from it to create a 1 class. The inheritance relationship states that a 1 is an 0. This means that 1 inherits the interface and implementation of 0, and 1 objects can be used to replace 0 objects in the applicationThis is known as the Liskov substitution principle. Nguyên tắc nói rằng “trong một chương trình máy tính, nếu 8 là một kiểu con của 9, thì các đối tượng kiểu 9 có thể được thay thế bằng các đối tượng kiểu 8 mà không làm thay đổi bất kỳ thuộc tính mong muốn nào của chương trình”Trong bài viết này, bạn sẽ thấy lý do tại sao bạn phải luôn tuân theo nguyên tắc thay thế Liskov khi tạo hệ thống phân cấp lớp của mình và những vấn đề bạn sẽ gặp phải nếu không tuân theo Thành phần là gì?Thành phần là một khái niệm mà các mô hình có một mối quan hệ. Nó cho phép tạo các kiểu phức tạp bằng cách kết hợp các đối tượng thuộc các kiểu khác. This means that a class 02 can contain an object of another class 03. This relationship means that a 02 has a 03UML represents composition as follows Composition is represented through a line with a diamond at the composite class pointing to the component class. The composite side can express the cardinality of the relationship. The cardinality indicates the number or valid range of 03 instances the 02 class will containIn the diagram above, the 08 represents that the 02 class contains one object of type 03. Cardinality can be expressed in the following ways
Ghi chú. Classes that contain objects of other classes are usually referred to as composites, where classes that are used to create more complex types are referred to as components Ví dụ: lớp 1 của bạn có thể được tạo bởi một đối tượng khác thuộc loại 18. Bố cục cho phép bạn thể hiện mối quan hệ đó bằng cách nói một 1 có một 18Thành phần cho phép bạn sử dụng lại mã bằng cách thêm các đối tượng vào các đối tượng khác, thay vì kế thừa giao diện và triển khai của các lớp khác. Cả lớp 1 và lớp 22 đều có thể tận dụng chức năng của lớp 18 thông qua thành phần mà không cần lấy lớp này từ lớp kiaTổng quan về tính kế thừa trong PythonMọi thứ trong Python đều là đối tượng. Mô-đun là đối tượng, định nghĩa lớp và hàm là đối tượng, và tất nhiên, đối tượng được tạo từ lớp cũng là đối tượng Kế thừa là một tính năng bắt buộc của mọi ngôn ngữ lập trình hướng đối tượng. Điều này có nghĩa là Python hỗ trợ tính kế thừa và như bạn sẽ thấy ở phần sau, đây là một trong số ít ngôn ngữ hỗ trợ tính đa kế thừa Khi bạn viết mã Python bằng các lớp, bạn đang sử dụng tính kế thừa ngay cả khi bạn không biết mình đang sử dụng nó. Hãy xem điều đó có nghĩa là gì Remove adsSiêu lớp đối tượngThe easiest way to see inheritance in Python is to jump into the and write a little bit of code. You’ll start by writing the simplest class possible >>>
You declared a class 24 that doesn’t do much, but it will illustrate the most basic inheritance concepts. Now that you have the class declared, you can use the 25 function to list its members>>>
returns a list of all the members in the specified object. You have not declared any members in 24, so where is the list coming from? You can find out using the interactive interpreter>>>
As you can see, the two lists are nearly identical. There are some additional members in 24 like 29 and 30, but every single member of the 31 class is also present in 24This is because every class you create in Python implicitly derives from 31. You could be more explicit and write 34, but it’s redundant and unnecessaryNote. In Python 2, you have to explicitly derive from 31 for reasons beyond the scope of this article, but you can read about it in the section of the Python 2 documentationExceptions Are an ExceptionEvery class that you create in Python will implicitly derive from 31. The exception to this rule are classes used to indicate errors by raising an exceptionYou can see the problem using the Python interactive interpreter >>>
You created a new class to indicate a type of error. Then you tried to use it to raise an exception. An exception is raised but the output states that the exception is of type 37 not 38 and that all 39 40 is a base class provided for all error types. To create a new error type, you must derive your class from 40 or one of its derived classes. The convention in Python is to derive your custom error types from 42, which in turn derives from 40The correct way to define your error type is the following >>>
As you can see, when you raise 38, the output correctly states the type of error raisedCreating Class HierarchiesInheritance is the mechanism you’ll use to create hierarchies of related classes. These related classes will share a common interface that will be defined in the base classes. Derived classes can specialize the interface by providing a particular implementation where applies In this section, you’ll start modeling an HR system. The example will demonstrate the use of inheritance and how derived classes can provide a concrete implementation of the base class interface The HR system needs to process payroll for the company’s employees, but there are different types of employees depending on how their payroll is calculated You start by implementing a 45 class that processes payroll
45 thực hiện một phương thức 47 để lấy một tập hợp các nhân viên và in ra số lượng 48, 49 của họ và sử dụng phương thức 47 hiển thị trên từng đối tượng nhân viênBây giờ, bạn triển khai lớp cơ sở 51 xử lý giao diện chung cho mọi loại nhân viên
51 là lớp cơ sở cho tất cả các loại nhân viên. Nó được xây dựng với một 48 và một 49. Những gì bạn đang nói là mọi 51 phải có một 48 được chỉ định cũng như một cái tênHệ thống nhân sự yêu cầu mọi 51 được xử lý phải cung cấp giao diện 47 trả về tiền lương hàng tuần cho nhân viên. Việc triển khai giao diện đó khác nhau tùy thuộc vào loại 51Ví dụ, nhân viên hành chính có mức lương cố định, vì vậy hàng tuần họ được trả số tiền như nhau
Bạn tạo một lớp dẫn xuất 60 kế thừa 51. Lớp được khởi tạo với 48 và 49 theo yêu cầu của lớp cơ sở và bạn sử dụng 64 để khởi tạo các thành viên của lớp cơ sở. Bạn có thể đọc tất cả về 64 trong Supercharge Your Classs With Python super() 60 cũng yêu cầu tham số khởi tạo 67 đại diện cho số tiền mà nhân viên kiếm được mỗi tuầnLớp cung cấp phương pháp 47 bắt buộc được sử dụng bởi hệ thống nhân sự. Việc triển khai chỉ trả về số tiền được lưu trữ trong 67Công ty cũng sử dụng công nhân sản xuất được trả lương theo giờ, vì vậy bạn thêm một số 70 vào hệ thống nhân sự
Lớp 70 được khởi tạo với 48 và 49, giống như lớp cơ sở, cộng với 74 và 75 cần thiết để tính bảng lương. Phương pháp 47 được thực hiện bằng cách trả lại số giờ đã làm việc nhân với tỷ lệ giờCuối cùng, công ty tuyển dụng các cộng tác viên bán hàng được trả lương cố định cộng với hoa hồng dựa trên doanh số bán hàng của họ, vì vậy bạn tạo một lớp 77
Bạn lấy được 77 từ 60 vì cả hai lớp đều có một 67 để xem xét. Đồng thời, 77 được khởi tạo với giá trị 82 dựa trên doanh số bán hàng cho nhân viên 47 tận dụng việc triển khai lớp cơ sở để truy xuất mức lương 84 và thêm giá trị hoa hồngVì 77 bắt nguồn từ 60, nên bạn có quyền truy cập trực tiếp vào thuộc tính 67 và bạn có thể đã triển khai 47 bằng cách sử dụng giá trị của thuộc tính đóVấn đề với việc truy cập trực tiếp thuộc tính là nếu việc triển khai 89 thay đổi, thì bạn cũng sẽ phải thay đổi việc triển khai 90. Tốt hơn là nên dựa vào phương thức đã được triển khai trong lớp cơ sở và mở rộng chức năng khi cầnBạn đã tạo hệ thống phân cấp lớp đầu tiên của mình cho hệ thống. Sơ đồ UML của các lớp trông như thế này Sơ đồ cho thấy hệ thống phân cấp thừa kế của các lớp. Các lớp dẫn xuất triển khai giao diện 91, được yêu cầu bởi 45. Việc triển khai 93 yêu cầu các đối tượng 94 được thông qua có chứa một triển khai 48, 49 và 97Các giao diện được biểu diễn tương tự như các lớp với từ giao diện phía trên tên giao diện. Tên giao diện thường được bắt đầu bằng chữ hoa 98Ứng dụng tạo nhân viên của mình và chuyển họ đến hệ thống tính lương để xử lý bảng lương 0Bạn có thể chạy chương trình trong dòng lệnh và xem kết quả 1Chương trình tạo ba đối tượng nhân viên, một đối tượng cho mỗi lớp dẫn xuất. Sau đó, nó tạo hệ thống tính lương và chuyển danh sách nhân viên sang phương thức 47 của nó, tính toán bảng lương cho từng nhân viên và in kết quảLưu ý cách lớp cơ sở 51 không định nghĩa phương thức 47. Điều này có nghĩa là nếu bạn định tạo một đối tượng 51 đơn giản và chuyển nó tới đối tượng 45, thì bạn sẽ gặp lỗi. Bạn có thể dùng thử trong trình thông dịch tương tác Python>>> 2Mặc dù bạn có thể khởi tạo một đối tượng 51 nhưng đối tượng đó không thể được sử dụng bởi 45. Tại sao? . Để đáp ứng các yêu cầu của 45, bạn sẽ muốn chuyển đổi lớp 51, hiện là lớp cụ thể, thành lớp trừu tượng. Bằng cách đó, không có nhân viên nào chỉ là một 51, mà là một người thực hiện 47Remove adsCác lớp cơ sở trừu tượng trong PythonLớp 51 trong ví dụ trên được gọi là lớp cơ sở trừu tượng. Các lớp cơ sở trừu tượng tồn tại để được kế thừa, nhưng không bao giờ được khởi tạo. Python cung cấp mô-đun 13 để định nghĩa các lớp cơ sở trừu tượngBạn có thể sử dụng dấu gạch dưới hàng đầu trong tên lớp của mình để thông báo rằng các đối tượng của lớp đó không nên được tạo. Dấu gạch dưới cung cấp một cách thân thiện để ngăn việc sử dụng sai mã của bạn, nhưng chúng không ngăn người dùng háo hức tạo các phiên bản của lớp đó Thư viện chuẩn trong Python cung cấp chức năng ngăn việc tạo các đối tượng từ các lớp cơ sở trừu tượng Bạn có thể sửa đổi việc triển khai lớp 51 để đảm bảo rằng nó không thể được khởi tạo 3Bạn lấy được 51 từ 17, biến nó thành một lớp cơ sở trừu tượng. Sau đó, bạn trang trí phương thức 47 với trình trang trí 19Thay đổi này có hai tác dụng phụ tốt đẹp
Bạn có thể thấy rằng các đối tượng thuộc loại 51 không thể được tạo bằng trình thông dịch tương tác>>> 4Đầu ra cho thấy rằng lớp không thể được khởi tạo vì nó chứa một phương thức trừu tượng 97. Các lớp dẫn xuất phải ghi đè phương thức để cho phép tạo các đối tượng thuộc loại của chúngKế thừa triển khai so với Kế thừa giao diệnKhi bạn dẫn xuất một lớp này từ một lớp khác, lớp dẫn xuất sẽ kế thừa cả hai
Hầu hết thời gian, bạn sẽ muốn kế thừa việc triển khai một lớp, nhưng bạn sẽ muốn triển khai nhiều giao diện, để các đối tượng của bạn có thể được sử dụng trong các tình huống khác nhau Các ngôn ngữ lập trình hiện đại được thiết kế dựa trên khái niệm cơ bản này. Chúng cho phép bạn kế thừa từ một lớp duy nhất, nhưng bạn có thể triển khai nhiều giao diện Trong Python, bạn không cần phải khai báo giao diện một cách rõ ràng. Bất kỳ đối tượng nào triển khai giao diện mong muốn đều có thể được sử dụng thay cho đối tượng khác. Điều này được gọi là. Gõ vịt thường được giải thích là “nếu nó hoạt động giống như một con vịt, thì đó là một con vịt. ” Để minh họa điều này, bây giờ bạn sẽ thêm một lớp 26 vào ví dụ trên mà lớp này không xuất phát từ lớp 51 5Lớp 26 không xuất phát từ lớp 51, nhưng nó hiển thị cùng một giao diện được yêu cầu bởi lớp 45. 93 yêu cầu một danh sách các đối tượng triển khai giao diện sau
Tất cả những yêu cầu này đều được lớp 26 đáp ứng, vì vậy lớp 45 vẫn có thể tính bảng lương của mìnhBạn có thể sửa đổi chương trình để sử dụng lớp 26 6Chương trình tạo một đối tượng 26 và thêm nó vào danh sách được xử lý bởi 45. Bây giờ bạn có thể chạy chương trình và xem đầu ra của nó 7Như bạn có thể thấy, 45 vẫn có thể xử lý đối tượng mới vì nó đáp ứng giao diện mong muốnVì bạn không cần phải xuất phát từ một lớp cụ thể để chương trình có thể sử dụng lại các đối tượng của bạn, bạn có thể hỏi tại sao bạn nên sử dụng tính kế thừa thay vì chỉ triển khai giao diện mong muốn. Các quy tắc sau đây có thể giúp bạn
Bây giờ bạn có thể làm sạch ví dụ trên để chuyển sang chủ đề tiếp theo. Bạn có thể xóa tệp 46 rồi sửa đổi mô-đun 21 về trạng thái ban đầu 8Bạn đã loại bỏ việc nhập mô-đun 13 vì lớp 51 không cần phải trừu tượng. Bạn cũng đã xóa phương thức trừu tượng 97 khỏi nó vì nó không cung cấp bất kỳ triển khai nàoVề cơ bản, bạn đang kế thừa việc triển khai các thuộc tính 48 và 49 của lớp 51 trong các lớp dẫn xuất của bạn. Vì 47 chỉ là một giao diện của phương thức 93, nên bạn không cần triển khai nó trong lớp cơ sở 51Lưu ý cách lớp 77 bắt nguồn từ lớp 60. Điều này có nghĩa là 77 kế thừa việc triển khai và giao diện của 60. Bạn có thể thấy cách phương thức 90 tận dụng việc triển khai lớp cơ sở vì nó dựa vào kết quả từ 62 để triển khai phiên bản của chính nóRemove adsVấn đề bùng nổ lớp họcNếu bạn không cẩn thận, tính kế thừa có thể dẫn bạn đến một cấu trúc phân cấp khổng lồ của các lớp khó hiểu và khó duy trì. This is known as the class explosion problem Bạn đã bắt đầu xây dựng hệ thống phân cấp lớp gồm 51 loại được sử dụng bởi 45 để tính bảng lương. Bây giờ, bạn cần thêm một số chức năng cho các lớp đó để chúng có thể được sử dụng với 65 mới 65 theo dõi năng suất dựa trên vai trò của nhân viên. Có nhiều vai trò nhân viên khác nhau
Với những yêu cầu đó, bạn bắt đầu thấy rằng 51 và các lớp dẫn xuất của nó có thể thuộc về một nơi nào đó khác với mô-đun 21 bởi vì bây giờ chúng cũng được sử dụng bởi 65Bạn tạo một mô-đun 70 và di chuyển các lớp đến đó 9Việc triển khai vẫn giữ nguyên, nhưng bạn chuyển các lớp sang mô-đun 94. Bây giờ, bạn thay đổi chương trình của mình để hỗ trợ thay đổi 0Bạn chạy chương trình và xác minh rằng nó vẫn hoạt động 1Với mọi thứ đã sẵn sàng, bạn bắt đầu thêm các lớp mới 2Đầu tiên, bạn thêm một lớp 72 bắt nguồn từ 60. Lớp tiết lộ một phương pháp 74 sẽ được sử dụng bởi hệ thống năng suất. Phương pháp lấy 75 nhân viên đã làm việcSau đó, bạn thêm 76, 77 và 78 rồi triển khai giao diện 74 để hệ thống năng suất có thể sử dụng chúngBây giờ, bạn có thể thêm lớp 80 3Lớp theo dõi nhân viên theo phương pháp 81 lấy danh sách nhân viên và số giờ cần theo dõi. Bây giờ bạn có thể thêm hệ thống năng suất vào chương trình của mình 4Chương trình tạo danh sách nhân viên các loại. Danh sách nhân viên được gửi đến hệ thống năng suất để theo dõi công việc của họ trong 40 giờ. Sau đó, cùng một danh sách nhân viên được gửi đến hệ thống bảng lương để tính lương cho họ Bạn có thể chạy chương trình để xem đầu ra 5Chương trình hiển thị các nhân viên làm việc trong 40 giờ thông qua hệ thống năng suất. Sau đó, nó tính toán và hiển thị bảng lương cho từng nhân viên Chương trình hoạt động như mong đợi, nhưng bạn phải thêm bốn lớp mới để hỗ trợ các thay đổi. Khi có các yêu cầu mới, hệ thống phân cấp lớp của bạn chắc chắn sẽ phát triển, dẫn đến vấn đề bùng nổ lớp trong đó hệ thống phân cấp của bạn sẽ trở nên lớn đến mức chúng sẽ khó hiểu và khó duy trì Sơ đồ sau đây cho thấy hệ thống phân cấp lớp mới Sơ đồ cho thấy hệ thống phân cấp lớp đang phát triển như thế nào. Các yêu cầu bổ sung có thể có tác động theo cấp số nhân về số lượng lớp học với thiết kế này Remove adsKế thừa nhiều lớpPython là một trong số ít ngôn ngữ lập trình hiện đại hỗ trợ đa kế thừa. Đa kế thừa là khả năng dẫn xuất một lớp từ nhiều lớp cơ sở cùng một lúc Đa kế thừa có tiếng xấu đến mức hầu hết các ngôn ngữ lập trình hiện đại không hỗ trợ nó. Thay vào đó, các ngôn ngữ lập trình hiện đại hỗ trợ khái niệm giao diện. Trong các ngôn ngữ đó, bạn kế thừa từ một lớp cơ sở duy nhất và sau đó triển khai nhiều giao diện, vì vậy lớp của bạn có thể được sử dụng lại trong các tình huống khác nhau Cách tiếp cận này đặt ra một số ràng buộc trong thiết kế của bạn. Bạn chỉ có thể kế thừa việc triển khai một lớp bằng cách xuất phát trực tiếp từ nó. Bạn có thể triển khai nhiều giao diện, nhưng bạn không thể kế thừa việc triển khai nhiều lớp Ràng buộc này tốt cho thiết kế phần mềm vì nó buộc bạn phải thiết kế các lớp của mình với ít phụ thuộc lẫn nhau hơn. Ở phần sau của bài viết này, bạn sẽ thấy rằng bạn có thể tận dụng nhiều triển khai thông qua thành phần, giúp phần mềm trở nên linh hoạt hơn. Tuy nhiên, phần này nói về đa thừa kế, vì vậy chúng ta hãy xem nó hoạt động như thế nào Hóa ra đôi khi thư ký tạm thời được thuê khi có quá nhiều giấy tờ phải làm. Lớp 82 thực hiện vai trò của lớp 76 trong ngữ cảnh của lớp 65, nhưng đối với mục đích trả lương, nó là lớp 70Bạn nhìn vào thiết kế lớp học của bạn. Nó đã phát triển một chút, nhưng bạn vẫn có thể hiểu nó hoạt động như thế nào. Có vẻ như bạn có hai lựa chọn
Sau đó, bạn nhớ rằng Python hỗ trợ đa kế thừa, vì vậy bạn quyết định xuất phát từ cả 76 và 70 6Python cho phép bạn kế thừa từ hai lớp khác nhau bằng cách chỉ định chúng giữa dấu ngoặc đơn trong khai báo lớp Bây giờ, bạn sửa đổi chương trình của mình để thêm nhân viên thư ký tạm thời mới 7You run the program to test it 8Bạn nhận được một ngoại lệ nói rằng 99 đối số vị trí được mong đợi, nhưng 00 đã được đưa raĐiều này là do bạn bắt nguồn từ 82 đầu tiên từ 76 và sau đó từ 70, vì vậy trình thông dịch đang cố gắng sử dụng 04 để khởi tạo đối tượngĐược rồi, hãy đảo ngược nó 9Bây giờ, hãy chạy lại chương trình và xem điều gì sẽ xảy ra 0Bây giờ có vẻ như bạn đang thiếu một tham số 67, tham số này cần thiết để khởi tạo 76, nhưng tham số đó không có ý nghĩa trong ngữ cảnh của một 82 bởi vì nó là một 70Có thể thực hiện 09 sẽ giúp ích 1Thử nó 2Điều đó cũng không hiệu quả. Được rồi, đã đến lúc bạn đi sâu vào trình tự giải quyết phương pháp Python (MRO) để xem điều gì đang xảy ra Khi một phương thức hoặc thuộc tính của một lớp được truy cập, Python sử dụng lớp MRO để tìm nó. MRO cũng được sử dụng bởi 64 để xác định phương thức hoặc thuộc tính nào sẽ gọi. Bạn có thể tìm hiểu thêm về 64 trong Supercharge Your Classs With Python super()Bạn có thể đánh giá MRO của lớp 82 bằng trình thông dịch tương tác>>> 3MRO hiển thị thứ tự mà Python sẽ tìm kiếm một thuộc tính hoặc phương thức phù hợp. Trong ví dụ này, đây là điều xảy ra khi chúng ta tạo đối tượng 82
Bởi vì các tham số không khớp, một ngoại lệ 37 được đưa raBạn có thể bỏ qua MRO bằng cách đảo ngược thứ tự thừa kế và gọi trực tiếp 22 như sau 4Điều đó giải quyết vấn đề tạo đối tượng, nhưng bạn sẽ gặp phải vấn đề tương tự khi cố tính bảng lương. Bạn có thể chạy chương trình để xem vấn đề 5Vấn đề bây giờ là do bạn đảo ngược thứ tự thừa kế, MRO đang tìm phương pháp 47 của 24 trước phương pháp trong 70. Bạn cần ghi đè 47 trong 82 và gọi triển khai đúng từ đó 6Phương thức 97 gọi trực tiếp 29 để đảm bảo rằng bạn nhận được kết quả chính xác. Bạn có thể chạy lại chương trình để thấy nó hoạt động 7Chương trình hiện hoạt động như mong đợi vì bạn đang buộc thứ tự giải quyết phương thức bằng cách thông báo rõ ràng cho trình thông dịch biết phương pháp nào chúng tôi muốn sử dụng Như bạn có thể thấy, đa thừa kế có thể gây nhầm lẫn, đặc biệt là khi bạn gặp phải Sơ đồ sau đây cho thấy vấn đề kim cương trong hệ thống phân cấp lớp học của bạn Sơ đồ cho thấy vấn đề kim cương với thiết kế lớp hiện tại. 82 sử dụng đa thừa kế để dẫn xuất từ hai lớp mà cuối cùng cũng dẫn xuất từ 51. Điều này khiến hai đường dẫn đến lớp cơ sở 51, đây là điều bạn muốn tránh trong thiết kế của mìnhVấn đề kim cương xuất hiện khi bạn đang sử dụng nhiều kế thừa và xuất phát từ hai lớp có lớp cơ sở chung. Điều này có thể gây ra phiên bản sai của một phương thức được gọi Như bạn đã thấy, Python cung cấp một cách để buộc gọi đúng phương thức và việc phân tích MRO có thể giúp bạn hiểu vấn đề Tuy nhiên, khi bạn gặp vấn đề về kim cương, tốt hơn hết là bạn nên suy nghĩ lại về thiết kế. Bây giờ bạn sẽ thực hiện một số thay đổi để tận dụng đa kế thừa, tránh vấn đề kim cương Các lớp dẫn xuất 51 được sử dụng bởi hai hệ thống khác nhau
Điều này có nghĩa là mọi thứ liên quan đến năng suất phải được đặt cùng nhau trong một mô-đun và mọi thứ liên quan đến bảng lương phải được đặt cùng nhau trong một mô-đun khác. Bạn có thể bắt đầu thực hiện các thay đổi đối với mô-đun năng suất 8Mô-đun 34 triển khai lớp 65, cũng như các vai trò liên quan mà nó hỗ trợ. Các lớp triển khai giao diện 74 theo yêu cầu của hệ thống, nhưng chúng không bắt nguồn từ 51Bạn có thể làm tương tự với mô-đun 21 9Mô-đun 21 thực hiện 45, tính toán bảng lương cho nhân viên. Nó cũng thực hiện các lớp chính sách cho bảng lương. Như bạn có thể thấy, các lớp chính sách không bắt nguồn từ 51 nữaBây giờ bạn có thể thêm các lớp cần thiết vào mô-đun 94 0Mô-đun 70 nhập các chính sách và vai trò từ các mô-đun khác và triển khai các loại 51 khác nhau. Bạn vẫn đang sử dụng đa kế thừa để kế thừa việc triển khai các lớp chính sách tiền lương và vai trò năng suất, nhưng việc triển khai từng lớp chỉ cần xử lý việc khởi tạoLưu ý rằng bạn vẫn cần khởi tạo rõ ràng các chính sách tiền lương trong hàm tạo. Bạn có thể thấy rằng phần khởi tạo của 72 và 76 giống hệt nhau. Ngoài ra, phần khởi tạo của 78 và 82 giống nhauBạn sẽ không muốn có kiểu sao chép mã này trong các thiết kế phức tạp hơn, vì vậy bạn phải cẩn thận khi thiết kế hệ thống phân cấp lớp Đây là sơ đồ UML cho thiết kế mới Sơ đồ hiển thị các mối quan hệ để xác định 76 và 82 bằng cách sử dụng đa thừa kế, nhưng tránh vấn đề kim cươngYou can run the program and see how it works 1Bạn đã thấy cách hoạt động của thừa kế và đa thừa kế trong Python. Bây giờ bạn có thể khám phá chủ đề sáng tác Remove adsThành phần trong PythonThành phần là một khái niệm thiết kế hướng đối tượng mà mô hình có một mối quan hệ. Trong thành phần, một lớp được gọi là hỗn hợp chứa một đối tượng của một lớp khác được gọi là thành phần. Nói cách khác, một lớp tổng hợp có một thành phần của lớp khác Thành phần cho phép các lớp tổng hợp sử dụng lại việc triển khai các thành phần mà nó chứa. Lớp tổng hợp không kế thừa giao diện lớp thành phần, nhưng nó có thể tận dụng việc triển khai của nó Mối quan hệ thành phần giữa hai lớp được coi là liên kết lỏng lẻo. Điều đó có nghĩa là những thay đổi đối với lớp thành phần hiếm khi ảnh hưởng đến lớp tổng hợp và những thay đổi đối với lớp tổng hợp không bao giờ ảnh hưởng đến lớp thành phần Điều này cung cấp khả năng thích ứng tốt hơn để thay đổi và cho phép các ứng dụng đưa ra các yêu cầu mới mà không ảnh hưởng đến mã hiện có Khi xem xét hai thiết kế phần mềm cạnh tranh, một dựa trên tính kế thừa và một dựa trên thành phần, giải pháp thành phần thường là linh hoạt nhất. Bây giờ bạn có thể xem cách sáng tác hoạt động Bạn đã sử dụng bố cục trong các ví dụ của chúng tôi. Nếu bạn nhìn vào lớp 51, bạn sẽ thấy rằng nó chứa hai thuộc tính
Hai thuộc tính này là các đối tượng mà lớp 51 có. Do đó, bạn có thể nói rằng một 51 có một 48 và có một tênMột thuộc tính khác cho một 51 có thể là một 58 2Bạn đã triển khai một lớp địa chỉ cơ bản chứa các thành phần thông thường cho một địa chỉ. Bạn đã đặt thuộc tính 59 là tùy chọn vì không phải địa chỉ nào cũng có thành phần đóBạn đã triển khai 60 để cung cấp một biểu diễn đẹp mắt của một 58. Bạn có thể thấy cách triển khai này trong trình thông dịch tương tác>>> 3Khi bạn 62 biến 63, phương thức đặc biệt 60 được gọi. Vì bạn đã quá tải phương thức để trả về một chuỗi được định dạng dưới dạng địa chỉ, nên bạn sẽ có một biểu diễn đẹp, dễ đọc. Quá tải toán tử và chức năng trong các lớp Python tùy chỉnh cung cấp một cái nhìn tổng quan về các phương thức đặc biệt có sẵn trong các lớp có thể được triển khai để tùy chỉnh hành vi của các đối tượng của bạnBây giờ bạn có thể thêm 58 vào lớp 51 thông qua thành phần 4Bây giờ, bạn khởi tạo thuộc tính 63 thành 68 để làm cho nó trở thành tùy chọn, nhưng bằng cách đó, giờ đây bạn có thể gán một 58 cho một 51. Cũng lưu ý rằng không có tham chiếu nào trong mô-đun 94 đến mô-đun 72Thành phần là một mối quan hệ kết hợp lỏng lẻo thường không yêu cầu lớp tổng hợp phải có kiến thức về thành phần Sơ đồ UML thể hiện mối quan hệ giữa 51 và 58 trông như thế nàySơ đồ cho thấy mối quan hệ thành phần cơ bản giữa 51 và 58Bây giờ bạn có thể sửa đổi lớp 45 để tận dụng thuộc tính 63 trong 51 5Bạn kiểm tra xem đối tượng 94 có địa chỉ không, nếu có thì in ra. Bây giờ bạn có thể sửa đổi chương trình để gán một số địa chỉ cho nhân viên 6Bạn đã thêm một vài địa chỉ vào các đối tượng 81 và 82. Khi bạn chạy chương trình, bạn sẽ thấy các địa chỉ được in 7Lưu ý cách đầu ra bảng lương cho các đối tượng 81 và 82 hiển thị địa chỉ nơi séc được gửiLớp 51 tận dụng việc triển khai lớp 58 mà không có bất kỳ kiến thức nào về đối tượng 58 là gì hoặc nó được biểu diễn như thế nào. Kiểu thiết kế này linh hoạt đến mức bạn có thể thay đổi lớp 58 mà không ảnh hưởng đến lớp 51Remove adsThiết kế linh hoạt với bố cụcThành phần linh hoạt hơn thừa kế vì nó mô hình hóa mối quan hệ kết hợp lỏng lẻo. Các thay đổi đối với một lớp thành phần có ảnh hưởng tối thiểu hoặc không ảnh hưởng đến lớp tổng hợp. Thiết kế dựa trên thành phần phù hợp hơn để thay đổi Bạn thay đổi hành vi bằng cách cung cấp các thành phần mới triển khai các hành vi đó thay vì thêm các lớp mới vào hệ thống phân cấp của bạn Hãy xem ví dụ đa thừa kế ở trên. Hãy tưởng tượng chính sách tiền lương mới sẽ ảnh hưởng đến thiết kế như thế nào. Cố gắng hình dung hệ thống phân cấp lớp sẽ như thế nào nếu cần có vai trò mới. Như bạn đã thấy trước đây, việc phụ thuộc quá nhiều vào tính kế thừa có thể dẫn đến bùng nổ giai cấp Vấn đề lớn nhất không phải là số lượng các lớp trong thiết kế của bạn nhiều như thế nào, mà là mối quan hệ giữa các lớp đó chặt chẽ đến mức nào. Các lớp liên kết chặt chẽ ảnh hưởng lẫn nhau khi các thay đổi được đưa ra Trong phần này, bạn sẽ sử dụng bố cục để thực hiện một thiết kế tốt hơn mà vẫn phù hợp với các yêu cầu của 45 và 65Bạn có thể bắt đầu bằng cách triển khai chức năng của 65 8Lớp 65 xác định một số vai trò bằng cách sử dụng mã định danh chuỗi được ánh xạ tới lớp vai trò thực hiện vai trò đó. Nó hiển thị một phương thức 94, được cung cấp một định danh vai trò, trả về đối tượng loại vai trò. Nếu vai trò không được tìm thấy, thì một ngoại lệ 95 sẽ được đưa raNó cũng hiển thị chức năng trước đó trong phương pháp 96, trong đó đưa ra một danh sách nhân viên, nó theo dõi năng suất của những nhân viên đóBây giờ bạn có thể triển khai các lớp vai trò khác nhau 9Mỗi vai trò mà bạn đã triển khai đều cho thấy một 97 chiếm số lượng 75 đã làm việc. Các phương thức trả về một chuỗi đại diện cho các nhiệm vụCác lớp vai trò độc lập với nhau, nhưng chúng hiển thị cùng một giao diện, vì vậy chúng có thể hoán đổi cho nhau. Sau này bạn sẽ thấy chúng được sử dụng như thế nào trong ứng dụng Bây giờ, bạn có thể triển khai 45 cho ứng dụng 0 45 lưu giữ cơ sở dữ liệu nội bộ về các chính sách trả lương cho từng nhân viên. Nó cho thấy một 01, được cung cấp cho một nhân viên 48, trả về chính sách trả lương của nó. If a specified 48 doesn’t exist in the system, then the method raises a 95 exceptionViệc triển khai 47 hoạt động giống như trước đây. Nó lấy danh sách nhân viên, tính bảng lương và in kết quảBây giờ bạn có thể thực hiện các lớp chính sách trả lương 1Trước tiên, bạn triển khai lớp 06 đóng vai trò là lớp cơ sở cho tất cả các chính sách trả lương. Lớp này theo dõi 74, phổ biến cho tất cả các chính sách trả lươngCác lớp chính sách khác bắt nguồn từ 06. Chúng tôi sử dụng tính kế thừa ở đây vì chúng tôi muốn tận dụng việc triển khai 06. Ngoài ra, 10, 11, và 12 là một 06 10 được khởi tạo với giá trị 67 sau đó được sử dụng trong 47. 11 được khởi tạo với 75 và triển khai 47 bằng cách tận dụng lớp cơ sở 74Lớp 12 bắt nguồn từ lớp 10 vì nó muốn kế thừa việc thực hiện của nó. Nó được khởi tạo với tham số 67, nhưng nó cũng yêu cầu tham số 24 24 được sử dụng để tính toán 26, được triển khai như một thuộc tính để nó được tính toán khi được yêu cầu. Trong ví dụ này, chúng tôi giả định rằng một lần bán hàng diễn ra sau mỗi 5 giờ làm việc và 26 là số lần bán hàng nhân với giá trị 24 12 triển khai phương pháp 47 bằng cách trước tiên tận dụng việc triển khai trong 10 và sau đó thêm hoa hồng đã tínhBây giờ bạn có thể thêm lớp 32 để quản lý địa chỉ nhân viên 2Lớp 32 giữ một cơ sở dữ liệu nội bộ gồm các đối tượng 58 cho mỗi nhân viên. Nó hiển thị một phương thức 35 trả về địa chỉ của nhân viên được chỉ định 48. Nếu nhân viên 48 không tồn tại, thì nó sẽ tăng 95Việc triển khai lớp 58 vẫn giống như trước đây 2Lớp quản lý các thành phần địa chỉ và cung cấp một biểu diễn đẹp về địa chỉ Cho đến nay, các lớp mới đã được mở rộng để hỗ trợ nhiều chức năng hơn, nhưng không có thay đổi đáng kể nào đối với thiết kế trước đó. Điều này sẽ thay đổi với thiết kế của mô-đun 70 và các lớp của nóBạn có thể bắt đầu bằng cách thực hiện một lớp 41 4 41 theo dõi tất cả nhân viên trong công ty. Đối với mỗi nhân viên, nó theo dõi 48, 49 và 45. Nó có một phiên bản của 65, 45 và 32. Những trường hợp này được sử dụng để tạo nhân viênNó hiển thị một thuộc tính 49 trả về danh sách nhân viên. Các đối tượng 51 được tạo trong một phương thức nội bộ 51. Lưu ý rằng bạn không có các loại lớp học 51 khác nhau. Bạn chỉ cần triển khai một lớp 51 duy nhất 5Lớp 51 được khởi tạo với các thuộc tính 48, 49 và 63. Nó cũng đòi hỏi năng suất 45 của nhân viên và chính sách 59Lớp đưa ra một phương pháp 88 mất nhiều giờ làm việc. Phương pháp này trước tiên truy xuất 61 từ 45. Nói cách khác, nó ủy quyền cho đối tượng 45 để thực hiện nhiệm vụ của mìnhTheo cách tương tự, nó ủy quyền cho đối tượng 59 để theo dõi công việc 75. 59, như bạn đã thấy, sử dụng số giờ đó để tính bảng lương nếu cầnSơ đồ sau đây cho thấy thiết kế thành phần được sử dụng Sơ đồ cho thấy thiết kế của các chính sách dựa trên thành phần. Có một 51 duy nhất bao gồm các đối tượng dữ liệu khác như 58 và phụ thuộc vào giao diện 69 và 91 để ủy thác công việc. Có nhiều triển khai của các giao diện nàyBây giờ bạn có thể sử dụng thiết kế này trong chương trình của mình 6Bạn có thể chạy chương trình để xem đầu ra của nó 7Thiết kế này được gọi là , trong đó các lớp bao gồm các chính sách và chúng ủy quyền cho các chính sách đó để thực hiện công việc Thiết kế dựa trên chính sách đã được giới thiệu trong cuốn sách Modern C++ Design và nó sử dụng siêu lập trình mẫu trong C++ để đạt được kết quả Python không hỗ trợ các mẫu, nhưng bạn có thể đạt được kết quả tương tự bằng cách sử dụng bố cục, như bạn đã thấy trong ví dụ trên Kiểu thiết kế này mang đến cho bạn tất cả sự linh hoạt mà bạn cần khi các yêu cầu thay đổi. Hãy tưởng tượng bạn cần thay đổi cách tính lương cho một đối tượng trong thời gian chạy Remove adsTùy chỉnh hành vi với thành phầnNếu thiết kế của bạn dựa trên sự kế thừa, bạn cần tìm cách thay đổi loại đối tượng để thay đổi hành vi của nó. Với bố cục, bạn chỉ cần thay đổi chính sách mà đối tượng sử dụng Hãy tưởng tượng rằng 81 của chúng ta đột nhiên trở thành nhân viên tạm thời được trả lương theo giờ. Bạn có thể sửa đổi đối tượng trong quá trình thực hiện chương trình theo cách sau 8Chương trình lấy danh sách nhân viên từ 41 và lấy nhân viên đầu tiên, đó là người quản lý mà chúng tôi muốn. Sau đó, nó tạo một 11 mới được khởi tạo ở mức $55 mỗi giờ và gán nó cho đối tượng người quản lýChính sách mới hiện được sử dụng bởi 45 để sửa đổi hành vi hiện có. Bạn có thể chạy lại chương trình để xem kết quả 9Tấm séc cho Mary Poppins, người quản lý của chúng tôi, hiện có giá 2200 đô la thay vì mức lương cố định 3000 đô la mà cô ấy có mỗi tuần Lưu ý cách chúng tôi đã thêm quy tắc kinh doanh đó vào chương trình mà không thay đổi bất kỳ lớp hiện có nào. Xem xét loại thay đổi nào sẽ được yêu cầu với thiết kế kế thừa Bạn sẽ phải tạo một lớp mới và thay đổi loại nhân viên quản lý. Không có khả năng bạn có thể thay đổi chính sách trong thời gian chạy Lựa chọn giữa Kế thừa và Thành phần trong PythonCho đến giờ, bạn đã thấy cách hoạt động của tính kế thừa và thành phần trong Python. Bạn đã thấy rằng các lớp dẫn xuất kế thừa giao diện và triển khai của các lớp cơ sở của chúng. Bạn cũng đã thấy rằng thành phần cho phép bạn sử dụng lại việc triển khai một lớp khác Bạn đã triển khai hai giải pháp cho cùng một vấn đề. Giải pháp đầu tiên sử dụng đa kế thừa và giải pháp thứ hai sử dụng thành phần Bạn cũng đã thấy rằng cách gõ vịt của Python cho phép bạn sử dụng lại các đối tượng với các phần hiện có của chương trình bằng cách triển khai giao diện mong muốn. Trong Python, không cần thiết phải xuất phát từ một lớp cơ sở để các lớp của bạn được sử dụng lại Tại thời điểm này, bạn có thể hỏi khi nào nên sử dụng thừa kế so với thành phần trong Python. Cả hai đều cho phép sử dụng lại mã. Kế thừa và thành phần có thể giải quyết các vấn đề tương tự trong chương trình Python của bạn Lời khuyên chung là sử dụng mối quan hệ tạo ra ít phụ thuộc hơn giữa hai lớp. Mối quan hệ này là thành phần. Tuy nhiên, sẽ có lúc việc kế thừa sẽ có ý nghĩa hơn Các phần sau đây cung cấp một số hướng dẫn để giúp bạn đưa ra lựa chọn đúng đắn giữa kế thừa và thành phần trong Python Kế thừa mô hình Mối quan hệ “Là A”Kế thừa chỉ nên được sử dụng để mô hình hóa một mối quan hệ. Nguyên tắc thay thế của Liskov nói rằng một đối tượng kiểu 6, kế thừa từ 7, có thể thay thế một đối tượng kiểu 7 mà không làm thay đổi các thuộc tính mong muốn của chương trìnhNguyên tắc thay thế của Liskov là hướng dẫn quan trọng nhất để xác định xem kế thừa có phải là giải pháp thiết kế phù hợp hay không. Tuy nhiên, câu trả lời có thể không đơn giản trong mọi tình huống. May mắn thay, có một bài kiểm tra đơn giản mà bạn có thể sử dụng để xác định xem thiết kế của mình có tuân theo nguyên tắc thay thế của Liskov hay không Giả sử bạn có một lớp 78 cung cấp cách triển khai và giao diện mà bạn muốn sử dụng lại trong một lớp khác 79. Suy nghĩ ban đầu của bạn là bạn có thể lấy 79 từ 78 và kế thừa cả giao diện và triển khai. Để chắc chắn đây là thiết kế phù hợp, bạn làm theo các bước sau
Nếu bạn có thể biện minh cho cả hai mối quan hệ, thì bạn không bao giờ nên kế thừa các lớp đó từ lớp khác. Hãy xem xét một ví dụ cụ thể hơn Bạn có một lớp 86 hiển thị một thuộc tính 87. Bạn cần một lớp 88, lớp này cũng có một lớp 87. Có vẻ như 88 là một loại đặc biệt của 86, vì vậy có lẽ bạn có thể rút ra từ nó và tận dụng cả giao diện và triển khaiTrước khi bắt đầu triển khai, bạn sử dụng nguyên tắc thay thế của Liskov để đánh giá mối quan hệ Một 88 là một 86 vì diện tích của nó được tính từ tích của ____61_______94 nhân với ____61_______95 của nó. Ràng buộc là 96 và 97 phải bằng nhauNó có ý nghĩa. Bạn có thể biện minh cho mối quan hệ và giải thích tại sao một 88 lại là một 86. Hãy đảo ngược mối quan hệ để xem nó có hợp lý khôngMột 86 là một 88 vì diện tích của nó được tính từ tích của 94 nhân với 95 của nó. Sự khác biệt là 04 và 05 có thể thay đổi độc lậpNó cũng có ý nghĩa. Bạn có thể biện minh cho mối quan hệ và mô tả các ràng buộc đặc biệt cho mỗi lớp. Đây là một dấu hiệu tốt rằng hai lớp này sẽ không bao giờ xuất phát từ nhau Bạn có thể đã thấy các ví dụ khác dẫn xuất 88 từ 86 để giải thích quyền thừa kế. Bạn có thể hoài nghi với bài kiểm tra nhỏ bạn vừa làm. Đủ công bằng. Let’s write a program that illustrates the problem with deriving 88 from 86Đầu tiên, bạn triển khai 86. Bạn thậm chí sẽ đóng gói các thuộc tính để đảm bảo rằng tất cả các ràng buộc đều được đáp ứng 0Lớp 86 được khởi tạo với một 95 và một 94, và nó cung cấp một thuộc tính 87 trả về diện tích. 95 và 94 được đóng gói để tránh thay đổi chúng trực tiếpBây giờ, bạn lấy được 88 từ 86 và ghi đè giao diện cần thiết để đáp ứng các ràng buộc của một 88 1Lớp 88 được khởi tạo với một 21, được sử dụng để khởi tạo cả hai thành phần của lớp cơ sở. Bây giờ, bạn viết một chương trình nhỏ để kiểm tra hành vi 2Chương trình tạo một 86 và một 88 và khẳng định rằng 87 của chúng được tính toán chính xác. Bạn có thể chạy chương trình và thấy rằng mọi thứ là 25 cho đến nay 3Chương trình thực thi chính xác, vì vậy có vẻ như 88 chỉ là trường hợp đặc biệt của 86Sau này, bạn cần hỗ trợ thay đổi kích thước đối tượng 86, vì vậy bạn thực hiện các thay đổi thích hợp cho lớp 4 29 lấy 30 và 31 cho đối tượng. Bạn có thể thêm đoạn mã sau vào chương trình để xác minh rằng nó hoạt động chính xác 5Bạn thay đổi kích thước đối tượng hình chữ nhật và xác nhận rằng khu vực mới là chính xác. Bạn có thể chạy chương trình để xác minh hành vi 3Xác nhận vượt qua và bạn thấy rằng chương trình chạy chính xác Vì vậy, điều gì sẽ xảy ra nếu bạn thay đổi kích thước một hình vuông? 7Bạn chuyển các tham số tương tự cho 33 mà bạn đã sử dụng với 34 và in vùng. Khi bạn chạy chương trình, bạn sẽ thấy 8Chương trình cho thấy diện tích mới là 35 giống như đối tượng 34. Vấn đề bây giờ là đối tượng 32 không còn đáp ứng ràng buộc của lớp 88 rằng 95 và 94 phải bằng nhauLàm thế nào bạn có thể khắc phục vấn đề đó? . Bạn có thể ghi đè 29 trong 32 và bỏ qua tham số 94, nhưng điều đó sẽ gây nhầm lẫn cho những người đang xem các phần khác của chương trình nơi mà ____64_______44 đang được thay đổi kích thước và một số trong số chúng không nhận được các khu vực mong đợi vì chúng thực sự là ____64_______45Trong một chương trình nhỏ như chương trình này, có thể dễ dàng phát hiện ra nguyên nhân của hành vi kỳ lạ, nhưng trong một chương trình phức tạp hơn, vấn đề sẽ khó tìm ra hơn Thực tế là nếu bạn có thể biện minh cho mối quan hệ thừa kế giữa hai lớp theo cả hai cách, thì bạn không nên lấy lớp này từ lớp khác Trong ví dụ này, không có nghĩa là 88 kế thừa giao diện và triển khai của 29 từ 86. Điều đó không có nghĩa là các đối tượng 88 không thể thay đổi kích thước. Có nghĩa là giao diện khác vì nó chỉ cần tham số 21Sự khác biệt trong giao diện này biện minh cho việc không bắt nguồn từ 88 từ 86 như bài kiểm tra đã khuyên ở trênRemove adsTrộn các tính năng với các lớp MixinMột trong những cách sử dụng đa kế thừa trong Python là mở rộng các tính năng của lớp thông qua mixin. Mixin là một lớp cung cấp các phương thức cho các lớp khác nhưng không được coi là một lớp cơ sở Mixin cho phép các lớp khác sử dụng lại giao diện và triển khai của nó mà không trở thành siêu lớp. Chúng triển khai một hành vi duy nhất có thể được tổng hợp cho các lớp không liên quan khác. Chúng tương tự như thành phần nhưng chúng tạo ra một mối quan hệ mạnh mẽ hơn Giả sử bạn muốn chuyển đổi các đối tượng thuộc một số loại nhất định trong ứng dụng của mình thành biểu diễn từ điển của đối tượng. Bạn có thể cung cấp phương thức 53 trong mọi lớp mà bạn muốn hỗ trợ tính năng này, nhưng việc triển khai phương thức 53 có vẻ rất giống nhauĐây có thể là một ứng cử viên sáng giá cho mixin. Bạn bắt đầu bằng cách sửa đổi một chút lớp 51 từ ví dụ thành phần 9Sự thay đổi là rất nhỏ. Bạn vừa thay đổi các thuộc tính 45 và 59 thành nội bộ bằng cách thêm dấu gạch dưới ở đầu vào tên của chúng. Bạn sẽ sớm thấy tại sao bạn lại thực hiện thay đổi đóBây giờ, bạn thêm lớp 58 0Lớp 58 hiển thị phương thức 53 trả về biểu diễn của chính nó dưới dạng từ điển. Phương pháp này được triển khai dưới dạng một cách hiểu 61 có nội dung: “Tạo ánh xạ từ điển 62 đến 63 cho mỗi mục trong 64 nếu 62 không phải là nội bộ. ”Ghi chú. Đây là lý do tại sao chúng tôi tạo các thuộc tính vai trò và bảng lương bên trong lớp 51, bởi vì chúng tôi không muốn đại diện cho chúng trong từ điểnAs you saw at the beginning, creating a class inherits some members from 31, and one of those members is 29, which is basically a mapping of all the attributes in an object to their valueBạn duyệt qua tất cả các mục trong 29 và lọc ra những mục có tên bắt đầu bằng dấu gạch dưới bằng cách sử dụng 70 71 kiểm tra giá trị được chỉ định. Nếu giá trị là một 31, thì nó sẽ xem liệu nó cũng có một thành viên 53 hay không và sử dụng nó để đại diện cho đối tượng. Mặt khác, nó trả về một biểu diễn chuỗi. Nếu giá trị không phải là 31, thì nó chỉ trả về giá trịBạn có thể sửa đổi lớp 51 để hỗ trợ mixin này 1Tất cả những gì bạn phải làm là kế thừa 58 để hỗ trợ chức năng. Sẽ rất tuyệt nếu hỗ trợ chức năng tương tự trong lớp 58, vì vậy thuộc tính 78 được biểu diễn theo cùng một cách 2Bạn áp dụng mixin cho lớp 58 để hỗ trợ tính năng. Bây giờ, bạn có thể viết một chương trình nhỏ để kiểm tra nó 3Chương trình triển khai một 80 chuyển đổi từ điển thành chuỗi JSON bằng cách sử dụng thụt đầu dòng để đầu ra trông đẹp hơnSau đó, nó lặp qua tất cả các nhân viên, in biểu diễn từ điển được cung cấp bởi 53. Bạn có thể chạy chương trình để xem đầu ra của nó 4Bạn đã tận dụng việc triển khai 58 trong cả hai lớp 51 và 58 ngay cả khi chúng không liên quan. Bởi vì 58 chỉ cung cấp hành vi, nó dễ dàng sử dụng lại với các lớp khác mà không gây ra vấn đềRemove adsThành phần cho Mô hình Mối quan hệ “Có A”Các mô hình thành phần a có mối quan hệ. Với thành phần, một lớp 02 có một thể hiện của lớp 03 và có thể tận dụng việc triển khai nó. Lớp 03 có thể được sử dụng lại trong các lớp khác hoàn toàn không liên quan đến lớp 02Trong ví dụ thành phần ở trên, lớp 51 có một đối tượng 58. 58 thực hiện tất cả các chức năng để xử lý địa chỉ và nó có thể được sử dụng lại bởi các lớp khácCác lớp khác như 41 hoặc 94 có thể sử dụng lại 58 mà không liên quan đến 51. Họ có thể tận dụng cùng một triển khai để đảm bảo rằng các địa chỉ được xử lý một cách nhất quán trên ứng dụngMột vấn đề bạn có thể gặp phải khi sử dụng thành phần là một số lớp của bạn có thể bắt đầu phát triển bằng cách sử dụng nhiều thành phần. Các lớp của bạn có thể yêu cầu nhiều tham số trong hàm tạo chỉ để truyền vào các thành phần mà chúng được tạo thành. Điều này có thể làm cho các lớp học của bạn khó sử dụng Một cách để tránh vấn đề là sử dụng Factory Method để xây dựng các đối tượng của bạn. Bạn đã làm điều đó với ví dụ thành phần Nếu bạn nhìn vào việc triển khai lớp 41, bạn sẽ nhận thấy rằng nó sử dụng 51 để xây dựng một đối tượng 51 với các tham số phù hợpThiết kế này sẽ hoạt động, nhưng lý tưởng nhất là bạn có thể xây dựng một đối tượng 51 chỉ bằng cách chỉ định một 48, ví dụ như 02Những thay đổi sau đây có thể cải thiện thiết kế của bạn. Bạn có thể bắt đầu với mô-đun 34 5Đầu tiên, bạn tạo nội bộ lớp 04, sau đó cung cấp biến nội bộ 05 cho mô-đun. Bạn đang thông báo với các nhà phát triển khác rằng họ không nên tạo hoặc sử dụng trực tiếp 04. Thay vào đó, bạn cung cấp hai chức năng, 07 và 81, làm giao diện chung cho mô-đun. Đây là những gì các mô-đun khác nên sử dụngĐiều bạn đang nói là 04 là một Singleton và chỉ nên có một đối tượng được tạo từ nóBây giờ, bạn có thể làm tương tự với mô-đun 21 6Một lần nữa, bạn tạo 11 nội bộ và cung cấp giao diện công khai cho nó. Ứng dụng sẽ sử dụng giao diện công khai để lấy chính sách và tính lươngBây giờ bạn sẽ làm tương tự với mô-đun 72 7Về cơ bản, bạn đang nói rằng chỉ nên có một 13, một 11 và một 04. Một lần nữa, mẫu thiết kế này được gọi là mẫu thiết kế Singleton, rất hữu ích cho các lớp chỉ nên có một thể hiện duy nhất.Bây giờ, bạn có thể làm việc trên mô-đun 70. Bạn cũng sẽ thực hiện một Singleton trong số 17, nhưng bạn sẽ thực hiện một số thay đổi bổ sung 8Trước tiên, bạn nhập các hàm và lớp có liên quan từ các mô-đun khác. 17 được tạo nội bộ và ở dưới cùng, bạn tạo một phiên bản duy nhất. Phiên bản này là công khai và là một phần của giao diện vì bạn sẽ muốn sử dụng nó trong ứng dụngYou changed the 19 attribute to be a dictionary where the key is the employee 48 and the value is the employee information. Bạn cũng đã sử dụng một phương pháp 21 để trả lại thông tin cho nhân viên được chỉ định 22Thuộc tính 23 hiện sắp xếp chìa khóa để trả lại cho nhân viên được sắp xếp theo số 48 của họ. Bạn đã thay thế phương thức đã xây dựng các đối tượng 51 bằng các lệnh gọi trực tiếp tới bộ khởi tạo 51Lớp 51 hiện được khởi tạo với lớp 48 và sử dụng các hàm công khai có trong các mô-đun khác để khởi tạo các thuộc tính của nóBây giờ bạn có thể thay đổi chương trình để kiểm tra các thay đổi 9Bạn nhập các hàm có liên quan từ các mô-đun 21 và 34, cũng như lớp 31 và 51. Chương trình sạch hơn vì bạn đã hiển thị giao diện cần thiết và đóng gói cách các đối tượng được truy cậpLưu ý rằng bây giờ bạn có thể tạo một đối tượng 51 trực tiếp chỉ bằng cách sử dụng đối tượng 48 của nó. Bạn có thể chạy chương trình để xem đầu ra của nó 0Chương trình hoạt động giống như trước đây, nhưng bây giờ bạn có thể thấy rằng một đối tượng 51 duy nhất có thể được tạo từ đối tượng 48 của nó và hiển thị biểu diễn từ điển của nóXem kỹ lớp học 51 1Lớp 51 là một hỗn hợp chứa nhiều đối tượng cung cấp các chức năng khác nhau. Nó chứa một 58 thực hiện tất cả các chức năng liên quan đến nơi nhân viên sống 51 cũng chứa vai trò năng suất do mô-đun 34 cung cấp và chính sách trả lương do mô-đun 21 cung cấp. Hai đối tượng này cung cấp các triển khai được sử dụng bởi lớp 51 để theo dõi công việc theo phương thức 88 và để tính bảng lương trong phương thức 47Bạn đang sử dụng bố cục theo hai cách khác nhau. Lớp 58 cung cấp dữ liệu bổ sung cho 51 trong đó các đối tượng vai trò và bảng lương cung cấp hành vi bổ sungTuy nhiên, mối quan hệ giữa 51 và các đối tượng đó được kết hợp lỏng lẻo, cung cấp một số khả năng thú vị mà bạn sẽ thấy trong phần tiếp theoThành phần để thay đổi hành vi thời gian chạyKế thừa, trái ngược với thành phần, là một mối quan hệ cặp đôi chặt chẽ. Với tính kế thừa, chỉ có một cách để thay đổi và tùy chỉnh hành vi. Ghi đè phương thức là cách duy nhất để tùy chỉnh hành vi của lớp cơ sở. Điều này tạo ra những thiết kế cứng nhắc, khó thay đổi Mặt khác, thành phần cung cấp một mối quan hệ được kết hợp lỏng lẻo cho phép các thiết kế linh hoạt và có thể được sử dụng để thay đổi hành vi trong thời gian chạy Hãy tưởng tượng bạn cần hỗ trợ chính sách khuyết tật dài hạn (LTD) khi tính bảng lương. Chính sách quy định rằng một nhân viên tại LTD sẽ được trả 60% tiền lương hàng tuần của họ với giả định 40 giờ làm việc Với thiết kế kế thừa, đây có thể là một yêu cầu rất khó hỗ trợ. Thêm nó vào ví dụ thành phần dễ dàng hơn nhiều. Hãy bắt đầu bằng cách thêm lớp chính sách 2Lưu ý rằng 49 không kế thừa 06, nhưng triển khai cùng một giao diện. Điều này là do việc triển khai hoàn toàn khác, vì vậy chúng tôi không muốn kế thừa bất kỳ triển khai nào của 06 49 khởi tạo 53 thành 68 và cung cấp một phương thức ____71_______55 nội bộ để đưa ra một ngoại lệ nếu ______71_______56 chưa được áp dụng. Sau đó, nó cung cấp một phương thức 57 để chỉ định 53Trước tiên, giao diện công khai kiểm tra xem 53 đã được áp dụng chưa, sau đó triển khai chức năng theo chính sách cơ sở đó. Phương thức 60 chỉ ủy quyền cho chính sách cơ sở và 47 sử dụng nó để tính toán 62 và sau đó trả về 60%Bây giờ bạn có thể thực hiện một thay đổi nhỏ đối với lớp 51 3Bạn đã thêm một phương pháp 64 áp dụng chính sách bảng lương hiện có cho chính sách mới và sau đó thay thế nó. Bây giờ bạn có thể sửa đổi chương trình để áp dụng chính sách cho đối tượng 51 4Chương trình truy cập vào 66, được đặt tại chỉ mục 67, tạo đối tượng 49 và áp dụng chính sách cho nhân viên. Khi 47 được gọi, thay đổi được phản ánh. Bạn có thể chạy chương trình để đánh giá đầu ra 5Số tiền séc cho nhân viên Kevin Bacon, là nhân viên bán hàng, hiện là $1080 thay vì $1800. Đó là vì 49 đã được áp dụng cho tiền lươngNhư bạn có thể thấy, bạn có thể hỗ trợ các thay đổi chỉ bằng cách thêm một chính sách mới và sửa đổi một vài giao diện. Đây là loại linh hoạt mà thiết kế chính sách dựa trên thành phần mang lại cho bạn Lựa chọn giữa Kế thừa và Thành phần trong PythonPython, với tư cách là một ngôn ngữ lập trình hướng đối tượng, hỗ trợ cả kế thừa và thành phần. Bạn đã thấy rằng kế thừa được sử dụng tốt nhất để mô hình hóa một mối quan hệ, trong khi các mô hình thành phần a có một mối quan hệ Đôi khi, thật khó để biết mối quan hệ giữa hai lớp nên như thế nào, nhưng bạn có thể làm theo các hướng dẫn sau
Phần kết luậnBạn đã khám phá tính kế thừa và thành phần trong Python. Bạn đã học về loại mối quan hệ mà thừa kế và thành phần tạo ra. Bạn cũng đã trải qua một loạt bài tập để hiểu cách kế thừa và thành phần được triển khai trong Python Trong bài viết này, bạn đã học cách
đề xuất đọcDưới đây là một số sách và bài viết khám phá sâu hơn về thiết kế hướng đối tượng và có thể hữu ích để giúp bạn hiểu cách sử dụng chính xác tính kế thừa và thành phần trong Python hoặc các ngôn ngữ khác
Đánh dấu là đã hoàn thành Xem ngay Hướng dẫn này có một khóa học video liên quan do nhóm Real Python tạo. Xem nó cùng với hướng dẫn bằng văn bản để hiểu sâu hơn. Kế thừa và thành phần. Hướng dẫn OOP Python 🐍 Thủ thuật Python 💌 Nhận một Thủ thuật Python ngắn và hấp dẫn được gửi đến hộp thư đến của bạn vài ngày một lần. Không có thư rác bao giờ. Hủy đăng ký bất cứ lúc nào. Được quản lý bởi nhóm Real Python Gửi cho tôi thủ thuật Python » Giới thiệu về Isaac Rodríguez Xin chào, tôi là Isaac. Tôi xây dựng, lãnh đạo và cố vấn cho các nhóm phát triển phần mềm và trong vài năm qua, tôi đã tập trung vào các dịch vụ đám mây và ứng dụng phụ trợ bằng Python cùng với các ngôn ngữ khác. Rất thích nghe từ bạn ở đây tại Real Python » Thông tin thêm về Y-sácMỗi hướng dẫn tại Real Python được tạo bởi một nhóm các nhà phát triển để nó đáp ứng các tiêu chuẩn chất lượng cao của chúng tôi. Các thành viên trong nhóm đã làm việc trong hướng dẫn này là Alex Aldren Joanna Bậc thầy Kỹ năng Python trong thế giới thực Với quyền truy cập không giới hạn vào Python thực Tham gia với chúng tôi và có quyền truy cập vào hàng nghìn hướng dẫn, khóa học video thực hành và cộng đồng các Pythonistas chuyên gia Nâng cao kỹ năng Python của bạn » Master Real-World Python Skills Tham gia với chúng tôi và có quyền truy cập vào hàng ngàn hướng dẫn, khóa học video thực hành và cộng đồng Pythonistas chuyên gia Nâng cao kỹ năng Python của bạn » What Do You Think? Đánh giá bài viết này Tweet Chia sẻ Chia sẻ EmailBài học số 1 hoặc điều yêu thích mà bạn đã học được là gì? Commenting Tips. Những nhận xét hữu ích nhất là những nhận xét được viết với mục đích học hỏi hoặc giúp đỡ các sinh viên khác. and get answers to common questions in our support portal What are the types of inheritance in Python?Types of inheritance. There are five types of inheritance in python programming. . 1). thừa kế duy nhất 2). Multiple inheritances 3). Multilevel inheritance 4). Hierarchical inheritance 5). Hybrid inheritance How many inheritance are there in Python?Depending upon the number of child and parent classes involved, there are four types of inheritance in python.
What is inheritance with example in Python?Mối quan hệ kế thừa xác định các lớp kế thừa từ các lớp khác dưới dạng lớp dẫn xuất, lớp con hoặc lớp con . Base class remains to be the source from which a subclass inherits. Ví dụ: bạn có lớp Cơ sở là “Động vật” và “Sư tử” là lớp Dẫn xuất. Quyền thừa kế sẽ là Sư tử là một con vật.
Which is not a type of inheritance in Python?Distributive is not a type of inheritance. |