INHERITANCE
The first thing to say about inheritance in Python is that the language allows one class to inherit the attributes and methods of another class. Subclasses or derived classes that are the most specialized inherit attributes and methods from their base classes or superclasses. Derived classes can override the behavior of inherited attributes (methods) and can add additional functionality that tends to specialize the class. Superclasses are generally more generic than their subclasses. When we create an instance of a subclass, this is also an instance of all the superclasses of the class of which it is an instance.
THE ISINSTANCE FUNCTION
There is an isinstance function that takes the instance as its first parameter and the class you want to verify as its second parameter. The function returns True if it is an instance of it. False otherwise. m1 being an instance of AClass is also implicitly an instance of BClass, moreover m1 inherits from BClass both the __init_ constructor and the printMessage(self) instance method as can be seen from the example.

OVERRIDE
With the override we can redefine the attributes (methods) in the subclasses. In the AClass derived class we are redefining the behavior of printMessage(self) albeit in a minimal way. When we create an instance of AClass that we call m1 and call printMessage(self) we are actually calling the method of the derived class as we have overwritten that of the base class. However, the code we wrote has a problem. If we also create a constructor in the derived class, the subclass constructor will be invoked when the instance is created, the superclass constructor will be ignored by not setting the message attribute correctly. This is because the superclass constructor is overridden. To solve this problem we use the super() function.

THE SUPER() FUNCTION
super() allows us to access superclass methods from subclasses. The super() function causes the superclass constructor to be executed, so by appropriately passing the message attribute, which we receive in the subclass constructor, all attributes will be initialized correctly.

PROPERTIES
Normally in Object Oriented languages there is a tendency to encapsulate or make private the data with getter and setter methods and make the methods public where necessary. Python does not fully support encapsulation. They can be created using a property’s getter and setter decorators.


class persona(object):
def __init__(self,nome,cognome,indirizzo):
self.__nome_ = nome
self.__cognome_ = cognome
self.__indirizzo_ = indirizzo
@property
def nome(self):
return self.__nome_
@nome.setter
def nome(self,nome):
self.__nome_ = nome
@property
def cognome(self):
return self.__cognome_
@cognome.setter
def cognome(self,cognome):
self.__cognome_ = cognome
@property
def indirizzo(self):
return self.__indirizzo_
@indirizzo.setter
def indirizzo(self,indirizzo):
self.__indirizzo_ = indirizzo
def denominazione(self):
s= f'Persona Nome: {self.nome} Cognome: {self.cognome} indirizzo: {self.indirizzo}'
print(s)
class utente(persona):
def __init__(self,id,numeroconto,saldo,nome,cognome,indirizzo):
self.__id_ = id
self.__numeroconto_ = numeroconto
self.__saldo_ = saldo
super().__init__(nome,cognome,indirizzo)
@property
def id(self):
return self.__id_
@id.setter
def id(self,id):
self.__id_ = id
@property
def numeroconto(self):
return self.__numeroconto_
@numeroconto.setter
def numeroconto(self,numeroconto):
self.__numeroconto_ = numeroconto
@property
def saldo(self):
return self.__saldo_
@saldo.setter
def saldo(self,saldo):
if (saldo < 0):
s=f'Impossibile impostare il saldo, valore passato: {saldo}'
print(s)
return
else:
self.__saldo_ = saldo
def saldoCorrente(self):
s = f'Utente: nome {self.nome} cognome {self.cognome} saldo {self.saldo}'
print(s)
class banca():
def __init__(self,id,denominazione,abi,cab,utente):
self.__id_=id
self.__denominazione_=denominazione
self.__abi_=abi
self.__cab_ = cab
self.__utente_=utente
@property
def id(self):
return self.__id_
@id.setter
def id(self,id):
self.__id_ = id
@property
def denominazione(self):
return self.__denominazione_
@denominazione.setter
def denominazione(self,denominazione):
self.__denominazione_ = denominazione
@property
def abi(self):
return self.__abi_
@abi.setter
def abi(self,abi):
self.__abi_ = abi
@property
def cab(self):
return self.__cab_
@cab.setter
def cab(self,cab):
self.__cab_ = cab
@property
def utente(self):
return self.__utente_
@utente.setter
def utente(self,utente):
self.__utente_ = utente
def preleva(self,importo,utente):
if importo < 0 or importo > utente.saldo:
s = f'Impossibile prelevare, importo passato: {importo} saldo: {utente.saldo}'
print(s)
return
else:
utente.saldo -= importo
def accredita(self,importo,utente):
if importo < 0:
s = f'Impossibile accreditare, valore passato: {importo}'
print(s)
return
else:
utente.saldo += importo
u1 = utente(12345,"AS67890OL",12000.0,'Mario','Rossi','via delle rose 54')
u2 = utente(678345,"AS67L768",2000.0,'Luigi','Verdi','via della fontana 7')
u1.denominazione()
u2.denominazione()
u1.saldoCorrente()
u2.saldoCorrente()
b1=banca(9873456,'UBI BANCA', 30600,10400,u1)
b2=banca(9876832,'UBI BANCA', 30600,10400,u2)
b1.preleva(5000.0,u1)
u1.saldoCorrente()
b2.accredita(3000.0,u2)
u2.saldoCorrente()
DEEPENING
Inheritance is a fundamental concept in object-oriented programming (OOP) in Python. It allows you to create a new class (derived class) that inherits attributes and methods from another class (base or parent class). This allows code to be reused and the functionality of existing classes to be extended.
Key concepts.
-Base (Parent) Class: The class from which attributes and methods are inherited.
-Derived Class (Child): The class that inherits from the base class.
Base syntax
Here is an example of how inheritance works in Python:
# Definizione della classe base
class Animale:
def __init__(self, nome):
self.nome = nome
def parla(self):
return f" fa un suono."
# Definizione della classe derivata
class Cane(Animale):
def __init__(self, nome, razza):
super().__init__(nome)
self.razza = razza
def parla(self):
return f" abbaia."
# Utilizzo delle classi
mio_cane = Cane("Fido", "Labrador")
print(mio_cane.parla()) # Output: Fido abbaia.
Explanation
1. Base Class (Animale): We define a class called Animale with a nome attribute and a parla method that returns a generic string.
2. Derived Class (Cane): The class Cane inherits from the class Animale. The super() function is used to call the constructor of the base class (__init__), allowing the derived class to initialize the attributes of the base class.
3. Method Overrides: In the Cane class, the parla method is overridden (override) to provide dog-specific behavior.
Multiple Inheritance.
Python also supports multiple inheritance, where a derived class can inherit from multiple base classes:
class A:
def metodo_a(self):
return "Metodo A"
class B:
def metodo_b(self):
return "Metodo B"
class C(A, B):
pass
oggetto = C()
print(oggetto.metodo_a()) # Output: Metodo A
print(oggetto.metodo_b()) # Output: Metodo B
In this example, class C inherits from both classes A and B, and thus has access to the methods of both. Inheritance is a powerful tool for modeling relationships between objects and promoting code reuse.
Leave A Comment