'''
ARGOMENTI:
---------------------------------------------------------------------

	classi
		Le classi sono usate per definire le caratteristiche di un oggetto: attributi e metodi.
		Le classi sono 'astratte', cioe' non si riferiscono a nessun oggetto specifico, 
		ma rappresentano un modello che puo' essere usato per creare "istanze". 
	
	
	
	istanze
		Le istanze sono oggetti creati a partire da una classe. 
		Una classe puo' essere usata per creare diverse istanze 
		dello stesso tipo ma con attributi diversi
		
		
		
	attributi
		Gli attributi sono dei valori associati all'istanza. 
		Gli attributi di ogni istanza sono separati.
		Per accedere a un attributo la forma e'  "istanza.attributo"


	metodi
		I metodi descrivono il comportamento dell'oggetto, 
		sono simili alle funzioni, e sono specifici per ogni classe. 
		E' possibile usare i metodi definiti dalla classe con ogni istanza, 
		utilizzando la forma "istanza.metodo()"
		
			__init__
				L'operazione di instanziazione (la "chiamata" di un oggetto classe) 
				crea un oggetto vuoto. In molti casi si preferisce che vengano 
				creati oggetti con uno stato iniziale noto. 
				Percio' una classe puo' definire un metodo speciale chiamato __init__().
		
			self:
				E' un argomento passato ai metodi che si riferisce all’istanza e,
				anche se i metodi devono "dichiararlo" esplicitamente, 
				non e' necessario passarlo quando il metodo viene richiamato.


					 
	
						
La programmazione ad oggetti potrebbe non essere la soluzione migliore se:

	1) la classe che vogliamo creare non rappresenta un oggetto
	2) vogliamo solo rappresentare dati (meglio usare "list", "dict" etc. etc.)
	3) vogliamo definire solo comportamenti (meglio usare funzioni);
	4) vogliamo creare una sola istanza della stessa classe 

'''

import random

class Cane:
	'''
		In Java, sia le 
			variabili "statiche"			("attributi di classe" in Python) 
			che le variabili di "istanza"	("attributi di istanza" in Python),
			
		sono definite immediatamente dopo la definizione della classe:
			le prime  con la parola chiave "static", 
			le seconde senza. 
		
		In Python solo 
			gli "attributi di classe"		posso essere definiti cosi'; 
			gli "attributi di istanza"		sono definiti nel metodo __init__.

	'''
	
	# attributo di classe   						
	numeroIstanze=0									# *
	
	
	# metodo __init__ / attributi di istanza
	def __init__(self,no,ra,an):
		Cane.numeroIstanze += 1
		self.nome=no
		self.razza=ra
		self.anni=int(an)
		self.zampe=4
	
	# metodo 
	def getEtaInAnniUmani(self):
		# ANNI UMANI: indicazioni trovate su internet
		if self.anni == 1:
			return 15
		elif self.anni == 2:
			return 24
		else:
			return 24 + ((self.anni - 2) * 4)
			
	# metodo 
	def saluto(self):
		saluti= ["BAU BAU!!!", "ARF ARF!!!", "GRRRR!!!", "YU YU YUUU" ]
		s=random.randint(0, len(saluti)-1)
		print (saluti[s])	
		
	# metodo
	def printInfo(self):
		print ("\n******************************")
		print("\t", self.nome)
		print ("---------------------------")
		print("Razza:\t\t", self.razza)
		print("Anni:\t\t", self.anni)
		print("Anni umani:\t", self.getEtaInAnniUmani())
		print("Zampe:\t\t", self.zampe)
			
	# metodo con parametro (incremento eta')
	def incrementaAnni(self, i):
		if i<0:
			print ("Impossibile effettuare l'incremento")
		else:
			self.anni += i
			print (	self.nome, 
					"- Incremento:",i, 
					"- Anni:", self.anni
				  )
	#metodo
	def azzoppato(self):
		self.zampe-=1
		
	


c1=Cane("Fido", "Dalmata", "5")
c2=Cane("Zeus", "Pastore silano", "2")
c1.printInfo()
c2.printInfo()

									
print ("\n\t  >> Numero di cani:",c2.numeroIstanze)  					# **  	


listaCani=[	Cane("Rex", "Pastore tedesco", "1"),
			Cane("Kimba", "Leonina", "5"), 
			Cane("Puppy", "Bastardino", "7")]
for i in listaCani:
	i.printInfo()
print ("\n\t >>> Numero di cani:",Cane.numeroIstanze) 					# **		


c1.printInfo()
print ("\n")
c1.incrementaAnni(3)
c1.incrementaAnni(-1)
c1.saluto()
c1.azzoppato()
c1.printInfo()


'''

# *		Gli "attributi di classe" possono essere usati come costanti 
		a livello di classe, ma non sono realmente costanti.
		Si possono anche modificare (come visto nell' esempio) 

# **	Gli attributi di classe sono disponibili sia attraverso 
		un riferimento diretto alla classe che attraverso una qualunque 
		istanza della classe.

'''



