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!
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
- Che cos'è l'ereditarietà nella programmazione orientata agli oggetti??
- Diverse forme di ereditarietà nella programmazione orientata agli oggetti
- Eredità unica
- Eredità multipla
- Eredità multilivello
- Eredità gerarchica
- Eredità ibrida
- Sostituzione del metodo
- 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:
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__)
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__ )
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()
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()
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()
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 risoluzioneIl "risoluzione" si riferisce alla capacità di prendere decisioni ferme e raggiungere gli obiettivi prefissati. In contesti personali e professionali, Implica la definizione di obiettivi chiari e lo sviluppo di un piano d'azione per raggiungerli. La risoluzione è fondamentale per la crescita personale e il successo in vari ambiti della vita, In quanto ti permette di superare gli ostacoli e mantenere la concentrazione su ciò che conta davvero.... de método (MRO ·) e Python. Possiamo trovare l'MRO di qualsiasi classe usando l'attributo __mro__
Child.__mro__
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 __-
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()
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()
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()
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()
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()
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()
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.
- 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()
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 parametriIl "parametri" sono variabili o criteri che vengono utilizzati per definire, misurare o valutare un fenomeno o un sistema. In vari campi come la statistica, Informatica e Ricerca Scientifica, I parametri sono fondamentali per stabilire norme e standard che guidano l'analisi e l'interpretazione dei dati. La loro corretta selezione e gestione sono fondamentali per ottenere risultati accurati e pertinenti in qualsiasi studio o progetto....: 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()
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')
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.
- 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()
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__
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..