Ereditarietà nella programmazione orientata agli oggetti

Contenuti

Panoramica

  • Scopri l'ereditarietà nella programmazione orientata agli oggetti e varie forme di ereditarietà
  • Comprendere l'override del metodo e la super funzione () nel mondo della programmazione orientata agli oggetti

introduzione

L'ereditarietà è uno degli aspetti più importanti della programmazione orientata agli oggetti (OOP). La chiave per comprendere l'ereditarietà è che fornisce il riutilizzo del codice. Invece di scrivere lo stesso codice, e di nuovo, possiamo semplicemente ereditare le proprietà di una classe nell'altra.

Questo, come puoi immaginare, risparmia un sacco di tempo. E il tempo è denaro nella scienza dei dati!

ereditarietà-in-oop-9792497

La programmazione orientata agli oggetti riguarda gli oggetti del mondo reale e l'ereditarietà è un modo di rappresentare le relazioni del mondo reale. Ecco un esempio: macchina, autobus, bicicletta – appartengono tutti a una categoria più ampia chiamata Veicolo. Ciò significa che hanno ereditato le proprietà dei veicoli di classe, vale a dire, tutti sono usati per il trasporto.

Possiamo rappresentare questa relazione nel codice con l'aiuto dell'ereditarietà.

Un'altra cosa interessante dell'ereditarietà è che è di natura transitiva.. Ma cosa significa?? Vedremo in dettaglio più avanti in questo articolo. Python supporta anche vari tipi di ereditarietà che tratterò in dettaglio in questo articolo..

Questo è il secondo articolo della serie di articoli relativi alla programmazione orientata agli oggetti. Leggi anche il primo articolo:

Sommario

  1. Che cos'è l'ereditarietà nella programmazione orientata agli oggetti??
  2. Diverse forme di ereditarietà nella programmazione orientata agli oggetti
    • Eredità unica
    • Eredità multipla
    • Eredità multilivello
    • Eredità gerarchica
    • Eredità ibrida
  3. Sostituzione del metodo
  4. La super funzione ()

Che cos'è l'ereditarietà nella programmazione orientata agli oggetti??

L'ereditarietà è la procedura in cui una classe eredita gli attributi e i metodi di un'altra classe. La classe le cui proprietà e metodi sono ereditati è nota come classe principale. E la classe che eredita le proprietà della classe principale è la classe Child.

La cosa interessante è che, insieme a proprietà e metodi ereditati, una clase hija puede tener sus propias propiedades y métodos.

Puede usar la siguiente sintaxis: para implementar la herencia en Python:

parent_class di classe:
body of parent class

class child_class( parent_class):
corpo della classe bambino

Veamos la implementación:

classe Auto:          #parent class

    def __init__(se stesso, nome, chilometraggio):
        self.name = name 
        self.mileage = mileage 

    def description(se stesso):                
        ritorno f"Il {self.name} auto dà il chilometraggio di {self.chilometraggio}km/l"

classe BMW(Auto):     #child class
    pass

class Audi(Auto):     #child class
    def audi_desc(se stesso):
        Restituzione "Questo è il metodo di descrizione della classe Audi."
obj1 = BMW("BMW serie 7",39.53)
Stampa(obj1.description())

obj2 = Audi("Audi A8 L",14)
Stampa(obj2.description())
Stampa(obj2.audi_desc())

Produzione:

A13-4443158

Hemos creado dos clases secundarias, vale a dire, “BMW” e “Audi”, que han heredado los métodos y propiedades de la clase principal “Coche ·”. Non abbiamo fornito funzioni e metodi aggiuntivi nella classe BMW. Considerando che esiste un metodo aggiuntivo all'interno della classe Audi.

Nota come gli oggetti nelle classi figlio possono accedere al metodo dell'istanza della descrizione () della classe principale con l'aiuto di obj1.description () y obj2.description (). E anche il metodo separato della classe Audi è accessibile da obj2.audi_desc ().

Possiamo controllare la classe base o genitore di qualsiasi classe usando un attributo di classe incorporato __basi__

Stampa(BMW.__basi__, Audi.__basi__)
screenshot-dal-2020-09-28-20-44-53-3987278

Come possiamo qui?, la classe base di entrambe le sottoclassi è Coche ·. Ora, Vediamo cosa succede quando __base__ viene utilizzato con la classe genitore Car:

Stampa( Auto.__basi__ )

screenshot-dal-2020-09-30-17-59-33-3279774

Ogni volta che creiamo una nuova classe in Python 3.x, eredita da una classe base incorporata chiamata Oggetto. In altre parole, class Object è la radice di tutte le classi.

Forme di ereditarietà nella programmazione orientata agli oggetti

Generalmente, Esistono cinque forme di ereditarietà basate sulla partecipazione di classe genitore-figlio.

1. Eredità unica

Questa è una forma di ereditarietà in cui una classe eredita solo una classe principale. Questa è la semplice forma di eredità e, così, conosciuto anche come eredità semplice.

classe Genitore:
  def f1(se stesso):
    Stampa("Funzione della classe madre.")

classe bambino(Genitore):
  def f2(se stesso):
    Stampa("Funzione della classe bambino.")

oggetto1 = Bambino()
oggetto1.f1()
oggetto1.f2()

screenshot-dal-2020-09-28-22-11-28-7257539

Qui, La classe figlio eredita solo una classe padre, così, questo è un esempio di eredità semplice.

2. Eredità multipla

Un'ereditarietà diventa eredità multiple quando una classe eredita più di una classe principale. La classe figlia dopo aver ereditato le proprietà da diverse classi principali ha accesso a tutti i suoi oggetti.

classe Genitore_1:
  def f1(se stesso):
    Stampa("Funzione della classe parent_1.")

classe Genitore_2:
  def f2(se stesso):
    Stampa("Funzione della classe parent_2.")

classe Genitore_3:
  def f3(se stesso):
    Stampa("funzione della classe parent_3.")

classe bambino(Genitore_1, Genitore_2, Genitore_3):
  def f4(se stesso):
    Stampa("Funzione della classe bambino.")

oggetto_1 = Bambino()
oggetto_1.f1()
oggetto_1.f2()
oggetto_1.f3()
oggetto_1.f4()

screenshot-da-2020-09-30-18-01-00-6896696

Qui abbiamo una classe Child che eredita le proprietà delle tre classi genitore Parent_1, Genitore_2 y Genitore_3. Tutte le classi hanno funzioni diverse e tutte le funzioni vengono chiamate utilizzando l'oggetto classe Child.

Ma supponiamo che una classe figlia erediti due classi che hanno la stessa funzione:

classe Genitore_1:
  def f1(se stesso):
    Stampa("Funzione della classe parent_1.")

classe Genitore_2:
  def f1(se stesso):
    Stampa("Funzione della classe parent_2.")

classe bambino(Genitore_1, Genitore_2):
  def f2(se stesso):
    Stampa("Funzione della classe bambino.")

Qui, Le classi Parent_1 e Parent_2 hanno la stessa funzione f1 (). Ora, quando l'oggetto della classe Child chiama f1 (), poiché la classe Child eredita le due classi genitore, Cosa pensi che dovrebbe succedere?

obj = bambino() 
obj.f1()

screenshot-dal-2020-09-30-18-04-07-6132602

Ma, Perché la funzione f1 non è stata ereditata? () dalla classe Parent_2?

In eredità multipla, la classe figlia prima cerca il metodo nella propria classe. Se non trovato, cerca le classi principali depth_first e ordina da sinistra a destra. Poiché questo era un esempio facile con solo due classi principali, possiamo vedere chiaramente che la classe Parent_1 è stata ereditata per prima, quindi la classe figlio cercherà il metodo nella classe Parent_1 prima di cercare nella classe Parent_2.

Ma per complicati problemi di ereditarietà, è difficile identificare l'ordine. Quindi, Il modo effettivo per farlo è chiamato Orden de risoluzione de método (MRO ·) e Python. Possiamo trovare l'MRO di qualsiasi classe usando l'attributo __mro__

Child.__mro__

Screenshot-da-2020-09-30-18-06-17-7768903

Ciò indica che la classe Child ha visitato prima la classe Parent_1 e poi Parent_2, Quindi il metodo F1 verrà chiamato () Parent_1.

Facciamo un esempio un po 'complicato in Python:

classe Genitore_1:
pass

class Parent_2:
pass

class Parent_3:
pass

class Child_1(Parent_1.Parent_2):
pass

class Child_2(Parent_2.Parent_3):
pass

class Child_3(Child_1.Child_2.Parent_3):
passaggio

Qui, La classe Child_1 eredita due classi: Parent_1 e Parent_2. La classe Child_2 eredita anche due classi: Genitore_2 y Genitore_3. Un'altra classe eredita Child_3 tre classi: Child_1, Child_2 e Parent_3.

Ora, solo guardando questo patrimonio, è abbastanza difficile determinare l'ordine di risoluzione del metodo per la classe Child_3. Quindi ecco l'effettivo utilizzo di __mro __-

screenshot-dal-2020-09-30-18-07-32-8298006

Possiamo vederlo prima, l'interprete cerca Child_3, poi Child_1 seguito da Parent_1, Bambino_2, Genitore_2 e Genitore_3 rispettivamente.

3. Eredità multilivello

Ad esempio, una class_1 è ereditata da una class_2 e anche questa class_2 è ereditata da class_3 e questo processo continua. Questo è noto come ereditarietà multilivello.. Capiamo con un esempio:

classe Genitore:
  def f1(se stesso):
    Stampa("Funzione della classe madre.")

classe Bambino_1(Genitore):
  def f2(se stesso):
    Stampa("Funzione della classe child_1.")

classe Bambino_2(Child_1):
  def f3(se stesso):
    Stampa("Funzione della classe child_2.")

obj_1 = Bambino_1()
obj_2 = Bambino_2()

obj_1.f1()
obj_1.f2()

Stampa("n")
obj_2.f1()
obj_2.f2()
obj_2.f3()

screenshot-dal-2020-09-30-18-09-52-9849898

Qui, class Child_1 eredita la classe Parent e la classe Child_2 eredita la classe Child_1. In questo Child_1 hai accesso alle funzioni f1 () y f2 () mentre Child_2 ha accesso alle funzioni f1 (), f2 () e f3 (). Se proviamo ad accedere alla funzione f3 () utilizzando l'oggetto classe Class_1, si verificherà un errore che indica:

L'oggetto "Child_1"’ non ha attributo 'f3'’

obj_1.f3()

screenshot-dal-2020-09-30-18-11-09-7482388

4- Eredità gerarchica

In questo, più classi Child ereditano una singola classe Parent. L'esempio fornito nell'introduzione dell'ereditarietà è un esempio di ereditarietà gerarchica in quanto le classi BMW e Audi ereditano la classe Car.

Per semplificare, vediamo un altro esempio:

classe Genitore:
def1(se stesso):
Stampa("Funzione della classe madre.")

classe Bambino_1(Genitore):
def2(se stesso):
Stampa("Funzione della classe child_1.")

classe Bambino_2(Genitore):
def3(se stesso):
Stampa("Funzione della classe child_2.")

obj_1 = Bambino_1()
obj_2 = Bambino_2()

obj_1.f1()
obj_1.f2()

Stampa('n')
obj_2.f1()
obj_2.f3()

screenshot-dal-2020-09-30-18-13-09-8467252

Qui due classi figlie ereditano la stessa classe genitore. La classe Child_1 ha accesso alle funzioni f1 () dalla classe Parent e alla funzione f2 () Di se stessa. Mentre la classe Child_2 ha accesso alle funzioni f1 () della classe Parent e della funzione f3 () Di se stessa.

5- Eredità ibrida

Quando c'è una combinazione di più di una forma di eredità, noto come ereditarietà ibrida. Sarà più chiaro dopo questo esempio:

classe Genitore:
  def f1(se stesso):
    Stampa("Funzione della classe madre.")

classe Bambino_1(Genitore):
  def f2(se stesso):
    Stampa("Funzione della classe child_1.")

classe Bambino_2(Genitore):
  def f3(se stesso):
    Stampa("Funzione della classe child_2.")

classe Bambino_3(Child_1, Bambino_2):
  def f4(se stesso):
    Stampa("Funzione della classe child_3.")

obj = Bambino_3()
obj.f1()
obj.f2()
obj.f3()
obj.f4()

screenshot-dal-2020-09-30-18-14-15-1161987

In questo esempio, due classi 'Child_1 ′ e’ Child_2 'sono derivati ​​dalla classe base’ Genitore "usando l'ereditarietà gerarchica". Un'altra classe "Child_3"’ è derivato dalle "classi Child_1"’ e 'Bambino_2'’ utilizzando più eredità. La "classe Child_3"’ ora derivato tramite ereditarietà ibrida.

Sostituzione del metodo

Il concetto di annullamento è molto importante nell'eredità. Concede la capacità speciale al bambino / sottoclassi per fornire un'implementazione specifica a un metodo che è già presente nelle sue classi genitori.

classe Genitore:
  def f1(se stesso):
    Stampa("Funzione della classe Genitore.")

classe bambino(Genitore):
  def f1(se stesso):
    Stampa("Funzione della classe Child.")

obj = bambino()
obj.f1()

screenshot-dal-2020-09-30-18-15-01-1521849

Qui, funzione f1 () dalla classe Child ha sovrascritto la funzione f1 () della classe Genitori. Ogni volta che l'oggetto della classe Child invoca f1 (), viene eseguita la funzione della classe Child. tuttavia, l'oggetto della classe principale può invocare la funzione f1 () della classe principale.

obj_2 = Genitore()
obj_2.f1()

screenshot-dal-2020-09-30-18-15-39-2868996

La super funzione ()

La super funzione () in Python restituisce un oggetto proxy che fa riferimento alla classe genitore usando il Super parola chiave. Questa super parola chiave () è fondamentalmente utile per accedere ai metodi sovrascritti della classe principale.

  1. In una gerarchia di classi con ereditarietà singola, Super aiuta a fare riferimento alle classi principali senza nominarle esplicitamente, che rende il codice più facile da mantenere.

    Ad esempio-

    classe Genitore:
      def f1(se stesso):
        Stampa("Funzione della classe Genitore.")
    
    classe bambino(Genitore):
      def f1(se stesso):
        super().f1()
        Stampa("Funzione della classe Child.")
    
    obj = bambino()
    obj.f1()

    screenshot-dal-2020-09-30-18-16-53-9118408

    Qui, con l'aiuto di super (). F1 (), è stato chiamato il metodo f1 () superclasse di classe Bambino, vale a dire, la classe Parent senza nominarla esplicitamente.

    Una cosa da notare qui è che la super classe () puede aceptar dos parametri: il primo è il nome della sottoclasse e il secondo è un oggetto che è un'istanza di quella sottoclasse. Vediamo come

    classe Genitore:
      def f1(se stesso):
        Stampa("Funzione della classe Genitore.")
    
    classe bambino(Genitore):
      def f1(se stesso):
        super( Bambino, se stesso ).f1()
        Stampa("Funzione della classe Child.")
    
    obj = bambino()
    obj.f1()

    screenshot-dal-2020-09-30-18-16-53-9118408

    Il primo parametro si riferisce alla sottoclasse Ragazzo, mentre il secondo parametro si riferisce all'oggetto Child che, in questo caso, è se stessi. Puoi vedere il risultato dopo aver usato super () e super (Bambino, se stesso) è lo stesso perché, e Python 3, super (Bambino, se stesso) è equivalente a sé ().

    Ora diamo un'occhiata a un altro esempio usando la funzione __init__.

    classe Genitore(oggetto):
      def__init__(se stesso, Nome del genitore):
        Stampa(Nome del genitore, 'è derivato da un'altra classe.')
    
    classe bambino(Genitore):
      def__init__(se stesso, Nome del bambino):
        Stampa(nome,'è una sottoclasse.')
        super().__dentro__(Nome del bambino)
    
    obj = bambino('Bambino')
    screenshot-dal-2020-09-30-18-18-16-3947931

    Quello che abbiamo fatto qui è chiamare la funzione __init__ della classe Parent (all'interno della classe Bambino) usando super () .__ dentro __ (Nome del bambino). E poiché il metodo __init__ della classe Parent richiede un argomento, è successo come “Nome del bambino”. Quindi, dopo aver creato l'oggetto della classe Child, prima è stata eseguita la funzione __init__ della classe Child, e poi la funzione __init__ della classe Parent.

  2. Il secondo caso d'uso è supportare eredità multiple cooperative in un ambiente di runtime dinamico.
    classe prima():
      def __init__(se stesso):
        Stampa("primo")
        super().__dentro__()
    
    classe Seconda():
      def __init__(se stesso):
        Stampa("secondo")
        super().__dentro__()
    
    classe terza(Secondo, Primo):
      def __init__(se stesso):
        Stampa("Terzo")
        super().__dentro__()
    
    obj = Terzo()

    screenshot-dal-2020-09-30-18-19-20-4144770
    La super chiamata () trova il seguente metodo nella MRO ad ogni passaggio, quindi anche Primo e Secondo devono averlo, altrimenti, l'esecuzione si interrompe alla fine di primo () .__ dentro__.

    Nota che la prima e la seconda superclasse sono Oggetto.

    Troviamo l'MRO di Third () pure-

    Terzo.__mro__

    screenshot-dal-2020-09-30-18-19-53-1265153

    L'ordine è Terzo> Secondo> Primo e lo stesso è l'ordine della nostra partenza.

Note finali

Completare, In questo articolo ho sviluppato il concetto di ereditarietà nella programmazione orientata agli oggetti in Python. Ho trattato varie forme di ereditarietà e alcuni dei concetti comuni di ereditarietà, come l'override del metodo e la super funzione ().

Spero che tu abbia capito i concetti spiegati in questo articolo. Fatemi sapere nei commenti qui sotto se avete domande..

Iscriviti alla nostra Newsletter

Non ti invieremo posta SPAM. Lo odiamo quanto te.