back to top

Python, programmazione ad oggetti ed ereditarietà

L’ereditarietà è un meccanismo grazie al quale una classe derivata (o child class) può acquisire le funzionalità definite in una classe base (o parent class) senza dover operare alcune modifica a carico di quest’ultima. L’utilizzo dell’ereditarietà presenta principalmente un vantaggio: consente di non dover riscrivere codice già digitato rendendolo riutilizzabile.

Definire una classe derivata

Per definire una classe derivata è sufficiente passare ad essa come argomento il nome della classe base. Immaginando di aver creato una parent class chiamata "Felino" si potrebbe definire una sua child class chiamata "Gatto" con questa semplice sintassi:

# Sintassi per la creazione di una classe derivata
# classe base
class Felino:
    ....

# classe derivata
class Gatto(Felino):
    ....

Una volta definita una classe derivata questa avrà a disposizione tutte le funzionalità originariamente associate alla classe base e queste ultime potranno essere utilizzate per operare sulle sue istanze.

Ereditarietà multipla in Python

Così come altri linguaggi avanzati che supportano il paradigma OOP, anche Python consente di sfruttare il meccanismo dell’ereditarietà multipla. Essa si basa sull’assunto che una classe derivata può ereditare da più di una classe base. A livello pratico ciò si traduce nella possibilità da parte di una child class di acquisire tutte le funzionalità definite nelle sue parent class.

Per rendere l’idea del concetto espresso è possibile proporre un semplice esempio:

# Ereditarietà multipla in Python
>>> class Madre:
pass

>>> class Padre:
pass

>>> class Figlia(Madre, Padre):
pass

Nel codice mostrato abbiamo due classi base, "Madre" e "Padre", e una classe denominata "Figlia" che viene definita attraverso il meccanismo dell’eredità multipla derivando dalle due parent class preesistenti.

Ereditarietà multilivello in Python

Un altro aspetto interessante riguarda la cosiddetta ereditarietà multilivello, sostanzialmente essa prevede che una classe derivata possa ereditare da una classe base che sia a sua volta la child class di un’altra classe base. Si tratta di un meccanismo gerarchico virtualmente replicabile all’infinito perché qualsiasi classe derivata può divenire base di una child class.

Nell’ereditarietà multilivello la classe derivata gerarchicamente inferiore eredita sia le funzionalità della child class da cui deriva che quelle ereditate da quest’ultima attraverso la sua parent class. Anche in questo caso può esserci d’aiuto un esempio:

>>> # Ereditarietà multilivello in Python
>>> class Madre:
pass

>>> class Figlia(Madre):
pass

>>> class Nipote(Figlia):
pass

In pratica la classe "Nipote" eredita dalla classe "Figlia" divenendone la child class, a sua volta la classe "Figlia" ha ereditato da "Madre" ed è quindi una sua derivata.

Tale meccanismo è insito nella natura di Python in quanto per questo linguaggio tutte le classi definite dagli utenti sono delle derivate della classe base Object, ne consegue che tutti gli oggetti sono nativamente anche istanze di quest’ultima.

Un esempio pratico di ereditarietà in Python

Si analizzi quindi l’esempio seguente:

# Definizione e utilizzo di una classe derivata
# parent class
class Felino:
    
    def __init__(self):
        print("Un felino gira libero per casa")

    def comesiChiama(self):
        print("Il felino si chiama Frazier")

    def graffia(self):
        print("Se ti avvicini graffia")

# child class
class Gatto(Felino):

    def __init__(self):
        super().__init__()
        print("Un gatto gira libero per casa")

    def comesiChiama(self):
        print("Il gatto si chiama Mayweather")

    def scappa(self):
        print("Se ti avvicini scappa")

obj = Gatto()
obj.comesiChiama()
obj.graffia()
obj.scappa()

Salvando il codice presentato in un file chiamato, ad esempio, "child.py" ed eseguendolo si otterrà un output come il seguente:

Un felino gira libero per casa
Un gatto gira libero per casa
Il gatto si chiama Mayweather
Se ti avvicini graffia
Se ti avvicini scappa

Il breve sorgente del precedente esempio inizia con la definizione di una parent class, "Felino", che viene implementata tramite l’introduzione di un costruttore e di due metodi ("comesiChiama()" e "graffia()"). Viene poi definita una child class, "Gatto", per ereditarietà, che introduce un nuovo metodo ("scappa()"). L’istanza di classe con generazione dell’oggetto viene operata sulla classe derivata ("obj = Gatto()").

La prima osservazione interessante riguarda il fatto che la classe derivata è in grado di modificare il comportamento della classe base, lo si nota facilmente dall’output prodotto in seguito alla chiamata del metodo "comesiChiama()" perché ad essere stampata è la stringa prevista dalla sua implementazione nella child class ("Il gatto si chiama Mayweather").

L’utilizzo del metodo "graffia()", e il suo output, evidenzia come tramite l’ereditarietà sia possibile richiamare un metodo definito nella parent class avendo operato l’istanza di classe esclusivamente a carico della child class.

Si noti infine l’impiego della funzione super(), detta funzione di override, prima del metodo __init__(), in questo modo è possibile integrare nella classe derivata l’argomento passato ad esso come parametro nella classe base.

Pubblicitร