18/09/2018, 16:26

Cách áp dụng đa hình cho các lớp trong Python 3

Giới thiệu Đa hình là khả năng tận dụng cùng một giao diện cho các biểu mẫu cơ bản khác nhau như loai du lieu hoặc là các lớp học. Giấy phép này chức năng để sử dụng các thực thể thuộc các loại khác nhau vào các thời điểm khác nhau. Đối với lập trình hướng đối tượng trong Python, điều này có ...

Giới thiệu

Đa hình là khả năng tận dụng cùng một giao diện cho các biểu mẫu cơ bản khác nhau như loai du lieu hoặc là các lớp học. Giấy phép này chức năng để sử dụng các thực thể thuộc các loại khác nhau vào các thời điểm khác nhau.

Đối với lập trình hướng đối tượng trong Python, điều này có nghĩa là một đối tượng cụ thể thuộc về một lớp cụ thể có thể được sử dụng giống như thể nó là một đối tượng khác thuộc về một lớp khác.

Đa hình cho phép linh hoạt và khớp nối lỏng lẻo để mã có thể được mở rộng và dễ dàng duy trì theo thời gian.

Hướng dẫn này sẽ đi qua việc áp dụng đa hình cho các lớp trong Python.

Đa hình là gì?

Đa hình là một tính năng quan trọng của định nghĩa lớp trong Python được sử dụng khi bạn có các phương thức thường được đặt tên trên các lớp hoặc các lớp con. Điều này cho phép các hàm sử dụng các đối tượng của bất kỳ lớp đa hình nào mà không cần phải nhận thức được sự phân biệt giữa các lớp.

Đa hình có thể được thực hiện thông qua di sản, với các lớp con sử dụng các phương thức lớp cơ sở hoặc ghi đè chúng.

Pythonâ € ™ s vịt gõ, một trường hợp nhập liệu động đặc biệt, sử dụng các kỹ thuật đặc trưng của đa hình, bao gồm Ràng buộc muộn và công văn động. Thuật ngữ â € œduck typingâ € bắt nguồn từ một trích dẫn của nhà văn James Whitcomb Riley: “Khi tôi nhìn thấy một con chim đi như một con vịt và bơi như một con vịt và quacks như một con vịt, tôi gọi con chim đó là một con vịt.” Được thiết kế bởi kỹ sư máy tính người Ý Alex Martelli trong một tin nhắn cho nhóm tin comp.lang.python, việc sử dụng kiểu gõ vịt có liên quan đến việc thiết lập sự phù hợp của một đối tượng cho một mục đích cụ thể. Khi sử dụng kiểu gõ bình thường, sự phù hợp này được xác định bởi kiểu của một đối tượng, nhưng với cách gõ vịt, sự hiện diện của các phương thức và thuộc tính được sử dụng để xác định sự phù hợp hơn là loại thực tế của đối tượng được đề cập. Đó là để nói, bạn kiểm tra xem đối tượng quacks như một con vịt và đi như một con vịt thay vì yêu cầu cho dù đối tượng con vịt.

Khi một số lớp hoặc các lớp con có cùng tên phương thức, nhưng các triển khai khác nhau cho cùng các phương thức này, các lớp là đa hình vì chúng đang sử dụng một giao diện duy nhất để sử dụng với các thực thể thuộc các kiểu khác nhau. Một hàm sẽ có thể đánh giá các phương thức đa hình này mà không biết các lớp nào được gọi.

Tạo các lớp đa hình

Để sử dụng đa hình, chúng tôi sẽ tạo hai lớp riêng biệt để sử dụng với hai đối tượng riêng biệt. Mỗi lớp riêng biệt này cần phải có một giao diện chung với nhau để chúng có thể được sử dụng đa hình, vì vậy chúng tôi sẽ cung cấp cho chúng các phương thức riêng biệt nhưng có cùng tên.

Chúng tôi sẽ tạo Shark lớp và một Clownfish mỗi lớp sẽ định nghĩa các phương thức cho swim(), swim_backwards()và skeleton().

polymorphic_fish.py

class Shark():
    def swim(self):
        print("The shark is swimming.")

    def swim_backwards(self):
        print("The shark cannot swim backwards, but can sink backwards.")

    def skeleton(self):
        print("The shark's skeleton is made of cartilage.")

class Clownfish():
    def swim(self):
        print("The clownfish is swimming.")

    def swim_backwards(self):
        print("The clownfish can swim backwards.")

    def skeleton(self):
        print("The clownfish's skeleton is made of bone.")

Trong đoạn mã trên, cả hai Shark và Clownfish lớp có ba phương thức có cùng tên chung. Tuy nhiên, mỗi chức năng của các phương thức này khác nhau đối với mỗi lớp.

Hãy tạo các lớp này thành hai đối tượng:

polymorphic_fish.py

...
sammy = Shark()
sammy.skeleton()

casey = Clownfish()
casey.skeleton()

Khi chúng tôi chạy chương trình với python polymorphic_fish.py lệnh, chúng ta có thể thấy rằng mỗi đối tượng hoạt động như mong đợi:

OutputThe shark's skeleton is made of cartilage.
The clownfish's skeleton is made of bone.

Bây giờ chúng ta có hai đối tượng sử dụng một giao diện chung, chúng ta có thể sử dụng hai đối tượng theo cùng một cách bất kể loại cá nhân của chúng.

Đa hình với phương pháp lớp

Để hiển thị cách Python có thể sử dụng từng loại lớp khác nhau theo cùng một cách, trước tiên chúng ta có thể tạo một for vòng lặp lặp lại qua tuple đối tượng. Sau đó, chúng ta có thể gọi các phương thức mà không phải lo lắng về kiểu lớp nào của từng đối tượng. Chúng ta sẽ chỉ giả định rằng các phương thức này thực sự tồn tại trong mỗi lớp.

polymorphic_fish.py

...
sammy = Shark()

casey = Clownfish()

for fish in (sammy, casey):
    fish.swim()
    fish.swim_backwards()
    fish.skeleton()

Chúng ta có hai vật thể, sammy của Shark lớp, và casey của Clownfish lớp học. Của chúng tôi for vòng lặp lặp qua các đối tượng này, gọi swim(), swim_backwards()và skeleton() phương pháp trên mỗi.

Khi chúng tôi chạy chương trình, đầu ra sẽ như sau:

OutputThe shark is swimming.
The shark cannot swim backwards, but can sink backwards.
The shark's skeleton is made of cartilage.
The clownfish is swimming.
The clownfish can swim backwards.
The clownfish's skeleton is made of bone.

Các for vòng lặp được lặp lại đầu tiên thông qua sammy sự khởi tạo của Shark lớp, sau đó là casey đối tượng của Clownfish lớp, vì vậy chúng tôi thấy các phương pháp liên quan đến Shark lớp đầu tiên, sau đó là Clownfish lớp học.

Điều này cho thấy rằng Python đang sử dụng các phương thức này theo cách mà không biết hoặc quan tâm chính xác loại lớp nào của từng đối tượng này. Đó là, sử dụng các phương pháp này theo cách đa hình.

Đa hình với chức năng

Chúng ta cũng có thể tạo ra một hàm có thể lấy bất kỳ đối tượng nào, cho phép đa hình.

Hãy tạo một hàm gọi là in_the_pacific() trong đó có một đối tượng chúng ta có thể gọi fish. Mặc dù chúng tôi đang sử dụng tên fish, bất kỳ đối tượng instantiated nào cũng có thể được gọi vào hàm này:

polymorphic_fish.py

…
def in_the_pacific(fish):

Tiếp theo, chúng tôi sẽ cung cấp cho chức năng một cái gì đó để làm điều đó sử dụng fish đối tượng chúng tôi truyền cho nó. Trong trường hợp này, chúng tôi sẽ gọi swim() các phương thức, mỗi phương thức được định nghĩa trong hai lớp Shark và Clownfish:

polymorphic_fish.py

...
def in_the_pacific(fish):
    fish.swim()

Tiếp theo, chúng tôi sẽ tạo các cảnh báo của cả hai Shark và Clownfish các lớp học nếu chúng tôi chưa có chúng. Với những người đó, chúng ta có thể gọi hành động của họ bằng cách sử dụng in_the_pacific() chức năng:

polymorphic_fish.py

...
def in_the_pacific(fish):
    fish.swim()

sammy = Shark()

casey = Clownfish()

in_the_pacific(sammy)
in_the_pacific(casey)

Khi chúng tôi chạy chương trình, đầu ra sẽ như sau:

OutputThe shark is swimming.
The clownfish is swimming.

Mặc dù chúng tôi đã vượt qua một đối tượng ngẫu nhiên (fish) vào in_the_pacific() khi định nghĩa nó, chúng ta vẫn có thể sử dụng nó một cách hiệu quả cho các instantiation của Shark và Clownfish các lớp học. Các casey đối tượng được gọi là swim() phương pháp được xác định trong Clownfish lớp học và sammy đối tượng được gọi là swim() phương pháp được xác định trong Shark lớp học.

Phần kết luận

Bằng cách cho phép các đối tượng khác nhau tận dụng các hàm và phương thức theo cách tương tự thông qua đa hình, việc sử dụng tính năng Python này cung cấp tính linh hoạt và khả năng mở rộng của mã hướng đối tượng của bạn.

0