class Pippo :
    n:int = 0
    def __init__(self, i:int) -> None:
        self._i:int = i  # il parametro i è pari
        Pippo.n += 1
        #self.n = self.n + i

    def __repr__(self) :
        return f"AAA i = {self._i}; n = {Pippo.n}; self.n = {self.n}"
    
    def __str__(self) :
        return f"i = {self._i}; n = {Pippo.n}" #; self.n = {self.n}"
    
    def __add__(self, y:"Pippo"):
        print ("Metodo add chiamato con i =", self._i)
        return Pippo(self._i+y._i)
    
    def __eq__(self, y:object) -> bool:
        if (not isinstance(y,Pippo) ):
            return False
        return self._i == y._i
        

    def incrementa(self, k:int=1):
        print (self.__class__)
        self._i += k

    def get_i (self) -> int:
        return self._i
    
    def set_i (self, valore:int) -> None:
        if valore % 2 == 0 :
            self._i = valore
        else:
            self._i = valore + 1 

    @classmethod
    def prova_metodo_classe (cls, topolino:int) -> int :
        print ("cls = ", cls)
        return cls.n + topolino
    
    # costruttore di copia realizzato tramite metodo di classe
    @classmethod
    def costruttore_copia (cls, sorgente:"Pippo") :
        return cls (sorgente._i)
    
    @staticmethod
    def prova_metodo_statico (topolino:int) -> int :
        return 2 * topolino + 1



#Pippo.n = 100
p = Pippo(10)
print ("Pippo.n = ",Pippo.n)

print (p)

p2 = Pippo (20)
print ("Pippo.n = ",Pippo.n)

print (p2)

p3 = p + p2 + p
print (p3)
p3.incrementa()
print (p3)
p3.incrementa(9)
print (p3)

print ("chiamata a metodo di classe :" ,Pippo.prova_metodo_classe(15))

print ("chiamata a metodo di classe :" ,p.prova_metodo_classe(15))

p3_copia = Pippo.costruttore_copia(p3)
print ("p3_copia: ",p3_copia)
print ("p3 == p3_copia", p3 == p3_copia)
print ("p3 is p3_copia", p3 is p3_copia)


p4 = p3
print ("p3 is p4", p3 == p4)
print (p3.get_i())
p3.set_i(11)
print (p3.get_i())

pass
