Polimorfismo

Python SELF IT
Livello 16 , Lezione 2
Disponibile

8.1 Polimorfismo

Il polimorfismo è uno dei concetti fondamentali della programmazione orientata agli oggetti (OOP), che consente agli oggetti di classi diverse di utilizzare la stessa interfaccia.

In Python, il polimorfismo viene raggiunto attraverso il dynamic typing e l'ereditarietà. Un aspetto importante del polimorfismo è l'overloading dei metodi e la loro sostituzione dai metodi della classe derivata.

Concetti principali del polimorfismo:

Interfaccia unica per oggetti diversi:

Il polimorfismo consente di utilizzare un'interfaccia unica per oggetti di classi diverse, che possono avere diverse implementazioni dei metodi.

Tipizzazione dinamica:

In Python, il tipo di una variabile viene determinato durante l'esecuzione, il che permette alle funzioni di lavorare con oggetti di qualsiasi classe, purché supportino l'interfaccia richiesta.

Ereditarietà:

Permette di creare gerarchie di classi, dove le sottoclassi ereditano proprietà e metodi della classe base, ma possono ridefinirli per la loro funzionalità specifica.

Esempi di polimorfismo:

Un semplice esempio di polimorfismo: tutte e tre le classi hanno un metodo chiamato move(). Questo significa che possiamo scrivere un codice che funzioni contemporaneamente con questi oggetti.


class Car:
    def move(self):
        pass
        
class Human:
    def move(self):
        pass
        
class Bird:
    def move(self):
        print("Car!")
        
car = Car()
human = Human()
bird = Bird()
        
for it in [car, human, bird]:
    it.move()

In questo caso, "interfaccia comune" è il nome del metodo, o la sua signature, se il metodo ha parametri.

8.2 Ridefinizione dei metodi

Il polimorfismo viene spesso utilizzato insieme all'ereditarietà per creare gerarchie di classi, dove la classe base definisce un'interfaccia comune e le sottoclassi implementano dettagli specifici.


class Employee:
    def get_salary(self):
        return 1000
        
class FullTimeEmployee(Employee):
    def get_salary(self):
        return 5000
        
class PartTimeEmployee(Employee):
    def get_salary(self):
        return 3000
        
class Intern(Employee):
    pass
        
def print_salary(employee):
    print(employee.get_salary())
        
employees = [FullTimeEmployee(), PartTimeEmployee(), Intern()]
        
for employee in employees:
    print_salary(employee)

Questo esempio è simile al precedente, ma ha una differenza importante: le nostre classi non devono avere il metodo get_salary, dal momento che esiste sempre nella classe base. Ora l'"interfaccia comune" di tutte le classi non è semplicemente il metodo get_salary(), ma proprio la classe Employee con tutti i suoi metodi e attributi.

8.3 Chiamata ai metodi della classe derivata

Dai un'occhiata al codice seguente:

Chiamiamo il metodo print_salary(), che esiste solo nella classe base Employee, e questa dalla classe base chiama un altro metodo della classe base - get_salary(). Quindi, quali stipendi verranno stampati a video?


class Employee:
    def print_salary(self):
        salary = self.get_salary()
        print(salary)
        
    def get_salary(self):
        return 1000
        
class FullTimeEmployee(Employee):
    def get_salary(self):
        return 5000
        
class PartTimeEmployee(Employee):
    def get_salary(self):
        return 3000
        
class Intern(Employee):
    pass
        
employees = [FullTimeEmployee(), PartTimeEmployee(), Intern()]
        
for employee in employees:
    employee.print_salary()

Importante! Leggi quanto segue - è importante.

Se chiamiamo il metodo print_salary(), per esempio, sulla classe FullTimeEmployee, verrà chiamato il metodo della classe base, poiché tale metodo non è dichiarato nella classe stessa.

Ma questo metodo print_salary() chiamerà il metodo get_salary() sull'oggetto self, che ha il tipo FullTimeEmployee, non Employee. Quindi verrà chiamato proprio il metodo get_salary() della classe FullTimeEmployee!

Inoltre, la classe FullTimeEmployee può chiamare il metodo get_salary() della classe base per le sue necessità. Ad esempio, possiamo voler calcolare lo stipendio in percentuale rispetto alla base:


class FullTimeEmployee(Employee):
    def get_salary(self):
        base_salary = super().get_salary()
        return base_salary * 5  
# 500%
class PartTimeEmployee(Employee): def get_salary(self): base_salary = super().get_salary() return base_salary * 3 # 300%

8.4 Sovraccarico dei metodi

Il sovraccarico dei metodi (method overloading) in Python è la capacità di creare più metodi con lo stesso nome, ma con parametri diversi. Tuttavia, il sovraccarico dei metodi non è supportato in modo diretto in Python, come avviene in altri linguaggi (ad esempio, C++ o Java).

In Python si può simulare il sovraccarico dei metodi attraverso l'uso di argomenti di default, *args e **kwargs.

Esempi di sovraccarico dei metodi

Possiamo realizzare una funzione che avrà comportamenti diversi a seconda del numero di argomenti passati. Questo si può fare in diversi modi, per esempio così:


class Example:
    def display(self, a=None, b=None):
        if a is not None and b is not None:
            print(a, b)
        elif a is not None:
            print(a)
        else:
            print("Nessun argomento")
        

obj = Example()
obj.display(1, 2)  # Output: 1 2
obj.display(1)  # Output: 1
obj.display()  # Output: Nessun argomento

Possiamo anche considerare il tipo di dati passato - semplicemente facendo un controllo sul tipo:


class Example:
    def mod(self, a, b):
        if type(a) == int and type(b) == int:
            print(a % b)
        elif type(a) == float or type(b) == float:
            print(round(a / b))
        else:
            print("Istruzione di aiuto: a e b devono essere int o float")
        

obj = Example()
obj.mod(5, 2)  # Output: 1
obj.mod(5.0, 2)  # Output: 2
obj.mod("5", 2)  # Output: Istruzione di aiuto: a e b devono essere int o float

Se vengono passati tipi di dati errati, è possibile visualizzare un'istruzione o anche un link alla documentazione online - anche questa è una soluzione molto popolare.

Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION