Python

ΕΝΟΤΗΤΑ 30 - Polymorphism

image description

Στο σημερινό δωρεάν μάθημα Python θα δούμε με ένα πρακτικό παράδειγμα πως χρησιμοποιείται η έννοια του πολυμορφισμού (polymorphism) στην Python και πως ακριβώς μπορεί να μας βοηθήσει η isinstance( ) function σε αυτή την διαδικασία.

Σαν πολυμορφισμό, στον προγραμματισμό, ορίζουμε την ικανότητα ενός αντικειμένου να αλλάζει μορφές. Αυτή είναι μια πολύ δυνατή και θεμελιώδης έννοια στον αντικειμενοστραφή προγραμματισμό.

Χωρίς να το γνωρίζετε, ήδη έχουμε χρησιμοποιήσει την έννοια του πολυμορφισμού στην Ενότητα 25 όπου μιλήσαμε για το πως μπορούμε να κάνουμε override τις functions που μια κλάση κληρονομεί από άλλη.

Υπάρχουν δύο βασικά χαρακτηριστικά που περιγράφουν την πολυμορφική λειτουργία ενός αντικειμένου:

  1. Είναι η δυνατότητα να ορίζουμε μια μέθοδο στην superclass και έπειτα να ορίσουμε μια μέθοδο με το ίδιο όνομα στην subclass. Όταν η subclass method έχει το ίδιο όνομα με εκείνο της superclass method τότε είναι αυτό που λέμε ότι η subclass method κάνει override την superclass method. Όπως ήδη ανάφερα πριν, την έχουμε δει αυτή την λειτουργία σε προηγούμενη ενότητα.
  2. Το δεύτερο χαρακτηριστικό είναι η ικανότητα να καλέσουμε την σωστή overridden μέθοδο ανάλογα με το είδος του αντικειμένου που χρησιμοποιούμε για να την καλέσουμε. Αν χρησιμοποιούμε αντικείμενο από την subclass τότε θα πρέπει να χρησιμοποιηθεί η μέθοδο αυτής της subclass. Αν όμως ένα αντικείμενο από την superclass χρησιμοποιείται για να καλέσει μια overridden μέθοδο, τότε η έκδοση της superclass είναι εκείνη που θα εκτελεστεί.

Για να καταλάβετε πως συνδυάζουνε μαζί οι έννοιες inheritance, override, και polymorphism ας δημιουργήσουμε ένα απλό παράδειγμα από την αρχή.

Ξεκινάμε με το να δημιουργήσουμε μια απλή κλάση με το όνομα Employee μέσα στην οποία περιέχονται οι __init__ , η jobTitle και η salary μέθοδοι. Με την __init__ απαιτούμε να λάβουμε το είδος του employee σαν πληροφορία για να την αποθηκεύσουμε σε μια μεταβλητή. Έπειτα καλούμε τις άλλες δύο functions για να δείξουμε πληροφορίες που σχετίζονται με το αντικείμενο από την συγκεκριμένη κλάση.

App.py


class Employee():

	def __init__(self, typeOfEmployee):
		self.__typeOfEmployee = typeOfEmployee

	def jobTitle(self):
		print("I am a ", self.__typeOfEmployee)

	def salary(self):
		print("Regular Employee Salary")

employee = Employee("Regular Employee")
employee.jobTitle()
employee.salary()

         

Output


I am a  Regular Employee
Regular Employee Salary	
	 

Τώρα ας προσθέσουμε μια subclass με το όνομα ExternalPartner. Για να είναι η ExternalPartner subclass της superclass Employee σημαίνει ότι υπάρχει κληρονομικότητα ανάμεσα στις δύο κλάσεις. Με άλλα λόγια η ExternalPartner κληρονομεί από την Employee.

App.py


class Employee():

	def __init__(self, typeOfEmployee):
		self.__typeOfEmployee = typeOfEmployee

	def jobTitle(self):
		print("I am a ", self.__typeOfEmployee)

	def salary(self):
	   print("Regular Employee Salary")

class ExternalPartner(Employee):
   def __init__(self):
	   Employee.__init__(self, 'External Partner')

   def salary(self):
	   print("External Partner Salary")

external = ExternalPartner()
external.jobTitle()
external.salary()

         

Output


I am a  External Partner
External Partner Salary	
	 

Δημιουργούμε ένα αντικείμενο από την κλάση ExternalPartner. Μετά καλούμε την μέθοδο jobTitle( ) την οποία δεν έχουμε κάνει override αλλά την χρησιμοποιούμε όπως την έχουμε κληρονομήσει. Επειδή έχουμε περάσει το όνομα External Partner στον constructor της Employee, μέσω της __init__ μεθόδου της ExternalPartner, θα λάβουμε τον σωστό τίτλο. Επίσης, η σωστή salary μέθοδο καλείται γιατί το αντικείμενο έχει δημιουργηθεί από την ExternalPartner κλάση.

Ας προσθέσουμε άλλη μια κλάση με την ίδια ακριβώς λογική και ας την ονομάσουμε Manager.

App.py


class Employee():

     def __init__(self, typeOfEmployee):
         self.__typeOfEmployee = typeOfEmployee

     def jobTitle(self):
         print("I am a ", self.__typeOfEmployee)

     def salary(self):
        print("Regular Employee Salary")

class ExternalPartner(Employee):
    def __init__(self):
        Employee.__init__(self, 'External Partner')

    def salary(self):
        print("External Partner Salary")

class Manager(Employee):
    def __init__(self):
        Employee.__init__(self, 'Manager')

    def salary(self):
        print("Manager Salary")

manager = Manager()
manager.jobTitle()
manager.salary()


         

Output


I am a  Manager
Manager Salary	
	 

Τώρα ας δούμε πως μπορούμε να χρησιμοποιήσουμε στον απόλυτο βαθμό την έννοια του πολυμορφισμού.

App.py


class Employee():

	def __init__(self, typeOfEmployee):
		self.__typeOfEmployee = typeOfEmployee

	def jobTitle(self):
		print("I am a ", self.__typeOfEmployee)

	def salary(self):
	   print("Regular Employee Salary")

class ExternalPartner(Employee):
   def __init__(self):
	   Employee.__init__(self, 'External Partner')

   def salary(self):
	   print("External Partner Salary")

class Manager(Employee):
   def __init__(self):
	   Employee.__init__(self, 'Manager')

   def salary(self):
	   print("Manager Salary")

def show_employee_info(employeetype):
   employeetype.jobTitle()
   employeetype.salary()

def main():
   regularemployee = Employee('Regular Employee')
   externalpartner = ExternalPartner()
   manager = Manager()

   print('-------------------------------')
   print('--------- Employee type -------')
   print('-------------------------------')
   show_employee_info(manager)
   print()
   show_employee_info(externalpartner)

main()

         

Output


-------------------------------
--------- Employee type -------
-------------------------------
I am a  Manager
Manager Salary

I am a  External Partner
External Partner Salary
		
	 

Μπορούμε λοιπόν να περάσουμε οποιοδήποτε αντικείμενο σαν μεταβλητή στην function show_employee_info( ) και οι αντίστοιχες μέθοδοι αυτού του αντικειμένου θα εκτελεστούν.

Εδώ όμως υπάρχει ένα πρόβλημα. Το πρόγραμμα μας περνούσε valid αντικείμενα στην μέθοδο show_employee_info. Τι θα συμβεί αν περάσουμε κάποιο αντικείμενο που δεν είναι είδος Employee? Το πρόγραμμα μας δεν θα εκτελεστεί γιατί θα έχουμε error.

Για να αποφύγουμε τέτοιου είδους λάθη, μπορούμε να χρησιμοποιήσουμε την function isinstance που δέχεται σαν πρώτη παράμετρο το αντικείμενο που θα ελέγξει και σαν δεύτερη παράμετρο την κλάση με την οποία θα συγκριθεί. Στο δικό μας παράδειγμα θα είναι isinstance(employeetype, Employee).

Ας τροποποιήσουμε τώρα το πρόγραμμα μας έτσι ώστε να κάνει τον σωστό έλεγχο για το αν κάποιο αντικείμενο είναι παράγωγο της κλάσης Employee ή όχι.

App.py


class Employee():

	def __init__(self, typeOfEmployee):
		self.__typeOfEmployee = typeOfEmployee

	def jobTitle(self):
		print("I am a ", self.__typeOfEmployee)

	def salary(self):
	   print("Regular Employee Salary")

class ExternalPartner(Employee):
   def __init__(self):
	   Employee.__init__(self, 'External Partner')

   def salary(self):
	   print("External Partner Salary")

class Manager(Employee):
   def __init__(self):
	   Employee.__init__(self, 'Manager')

   def salary(self):
	   print("Manager Salary")

def show_employee_info(employeetype):
   if isinstance(employeetype, Employee):
	   employeetype.jobTitle()
	   employeetype.salary()
   else:
	   print("You are not an employee")

def main():
   regularemployee = Employee('Regular Employee')
   externalpartner = ExternalPartner()
   manager = Manager()

   print('-------------------------------')
   print('--------- Employee type -------')
   print('-------------------------------')
   show_employee_info(manager)
   print()
   show_employee_info(externalpartner)
   print()
   show_employee_info("I am Michail")

main()


         

Output


-------------------------------
--------- Employee type -------
-------------------------------
I am a  Manager
Manager Salary

I am a  External Partner
External Partner Salary

You are not an employee
	
	 

ΕΙΣΗΓΗΤΗΣ

Merry Jhonson

Μιχάλης Κασάπογλου

Ο Μιχάλης Κασάπογλου, είναι ένας από τους πιο έμπειρους τεχνικούς εκπαιδευτές στον χώρο του προγραμματισμού με πάνω από 20 χρόνια εμπειρία. Έχει εργαστεί σαν IT Operations Manager, Senior Programmer, και Training Team Leader ενώ κατέχει και αρκετές πιστοποιήσεις που καλύπτουν ένα μεγάλο φάσμα τεχνολογιών στο προγραμματισμό, σε βάσεις δεδομένων και cloud. Στον ελεύθερο του χρόνο διατηρεί ένα τεχνολογικό blog στο οποίο θα βρείτε αρκετά δωρεάν μαθήματα προγραμματισμού για αρχάριους.

loader