Criação de classe (atributos com __ são privados):
class Caneta:
__modelo = ""
__cor = ""
__ponta = 0
__tampada = False
def tampar(self):
self.__tampada = True
def destampar(self):
self.__tampada = False
def status(self):
print("Modelo: {}".format(self.__modelo))
print("Cor: {}".format(self.__cor))
print("Ponta: {}".format(self.__ponta))
print("Tampada: {}".format(self.__tampada))
Instanciação básica:
c1 = Caneta()
c1.status()
Quando criamos uma classe, temos mais trabalho para fazê-la, mas depois que ela está pronta, podemos criar quantos objetos precisarmos vindos dessa mesma classe, e o programa principal fica mais simples, menor e mais natural. Os objetos criados dessa mesma classe são independentes entre si e o status de um não interfere no outro. Essa é uma das vantagens da orientação a objetos.
PS: Para pegar o nome da classe, use self.__class__.__name__
.
Classe com getters, setters, construtor e destrutor:
class Caneta:
__modelo = ""
__cor = ""
__ponta = 0
__tampada = False
def tampar(self):
self.__tampada = True
def destampar(self):
self.__tampada = False
def status(self):
print("Modelo: {}".format(self.__modelo))
print("Cor: {}".format(self.__cor))
print("Ponta: {}".format(self.__ponta))
print("Tampada: {}".format(self.__tampada))
# Construtor
def __init__(self, m, c, p):
self.__modelo = m
self.__cor = c
self.__ponta = p
self.tampar()
# Destrutor
def __del__(self):
print("Objeto Caneta Destruído com Sucesso!")
def getModelo(self):
return self.__modelo
def getPonta(self):
return self.__ponta
def setModelo(self, modelo):
self.__modelo = modelo
def setPonta(self, ponta):
self.__ponta = ponta
PS: Caso num construtor precise inicializar um atributo como nulo, use None
.
Uso:
c1 = Caneta("BIC", "Azul", 0.4)
c2 = Caneta("Pilot", "Verde", 1.0)
c1.status()
c2.status()
del c1
del c2
Veja um exemplo de classe somente com métodos e atributos estáticos:
class Lampada:
__preco = 9.50 # Simulação de estático
__acesa = False
@staticmethod
def custo(): # Método estático não tem self, atributos também não
print("A lâmpada custa R${:.2f}.".format(Lampada.__preco))
@staticmethod
def acender():
print("A lâmpada está acesa!")
Lampada.__acesa = True
@staticmethod
def apagar():
print("A lâmpada está apagada!")
Lampada.__acesa = False
E o uso:
from Lampada import Lampada
Lampada.custo() # Método estático.
Lampada.acender()
Lampada.apagar()
Lampada.__custo = 8.25 # Atributo estático
PS: Métodos estáticos só podem trabalhar outros métodos e atributos quando estes também forem estáticos, e não podem ser sobrepostos. E atributos estáticos é recomendável eles serem inicializados.
Simulação de interface com classe só com método abstratos:
from abc import ABC, abstractmethod
class Controlador(ABC):
@abstractmethod
def ligar(self):
pass
@abstractmethod
def desligar(self):
pass
@abstractmethod
def abrirMenu(self):
pass
@abstractmethod
def fecharMenu(self):
pass
@abstractmethod
def maisVolume(self):
pass
@abstractmethod
def menosVolume(self):
pass
@abstractmethod
def play(self):
pass
@abstractmethod
def pause(self):
pass
Classe herdeira:
from Controlador import Controlador
class ControleRemoto(Controlador):
__volume = 0
__ligado = False
__tocando = False
def ligar(self):
self.setLigado(True)
def desligar(self):
self.setLigado(False)
def abrirMenu(self):
print("Está ligado? {}".format(self.getLigado()))
print("Está tocando? {}".format(self.getTocando()))
print("Volume: {}".format(self.getVolume()), end="")
for i in range(0, self.getVolume() + 1, 2):
print("|", end="")
print("")
def fecharMenu(self):
print("Fechando Menu...")
def maisVolume(self):
if self.getLigado():
if self.getVolume() < 100:
self.setVolume(self.getVolume() + 2)
else:
print("ERRO! Está Desligado, Não Posso Aumentar o Volume!")
def menosVolume(self):
if self.getLigado():
if self.getVolume() > 0:
self.setVolume(self.getVolume() - 2)
else:
print("ERRO! Está Desligado, Não Posso Diminuir o Volume!")
def play(self):
if self.getLigado() and not self.getTocando():
self.setTocando(True)
def pause(self):
if self.getLigado() and self.getTocando():
self.setTocando(False)
def __init__(self):
self.__volume = 50
self.__ligado = False
self.__tocando = False
def __del__(self):
print("Objeto ControleRemoto Destruído com Sucesso!")
def getVolume(self):
return self.__volume
def getLigado(self):
return self.__ligado
def getTocando(self):
return self.__tocando
def setVolume(self, volume):
self.__volume = volume
def setLigado(self, ligado):
self.__ligado = ligado
def setTocando(self, tocando):
self.__tocando = tocando
Instanciação:
from ControleRemoto import ControleRemoto
c = ControleRemoto()
c.ligar()
c.maisVolume()
c.abrirMenu()
del c
PS: Ao chamar métodos da classe pai na classe filha, use o método super()
seguido do nome do método, como super().__init__()
(no caso do construtor), pode ser feito com qualquer método. Caso precise atribuir valor nulo à algum atributo ou variável, use None
.
Exemplo com herança e polimorfismo:
from abc import ABC, abstractmethod
class Mamifero(ABC):
@abstractmethod
def lutar(self):
pass
def respirar(self):
print("Eu Respiro!")
def mamar(self):
print("Eu Mamo!")
Classe herdeira:
from Mamifero import Mamifero
class Gato(Mamifero):
# Sobrescrevendo método abstrato
def lutar(self):
print("Gatos Lutam Arranhando!")
def arranhar(self):
print("Eu Arranho!")
Outra classe herdeira:
from Mamifero import Mamifero
class Humano(Mamifero):
# Sobrescrevendo método abstrato
def lutar(self):
print("Humanos Lutam com Armas!")
def falar(self):
print("Eu Falo!")
E a implementação:
from Gato import *
from Humano import *
bicho = Mamifero() # Dará erro por ser abstrata
homem = Humano()
bichano = Gato()
homem.falar()
homem.respirar()
homem.lutar()
bichano.arranhar()
bichano.respirar()
bichano.lutar()
PS: O Python permite herança múltipla, no caso, separe as classes pai por virgulas, como class NomeClasseFilha(NomeClassePai1, NomeClassePai2):
.
Vamos supor essa classe:
class Pilha:
__marca = ""
__carga = 0
def __init__(self, marca):
self.__marca = marca
self.__carga = 100
def apresentacao(self):
print(f"A marca da pilha é {self.__marca}.")
print(f"A carga da pilha é {self.__carga}%.")
def getMarca(self):
return self.__marca
def getCarga(self):
return self.__carga
def setMarca(self, marca):
self.__marca = marca
def setCarga(self, carga):
self.__carga = carga
Nós podemos fazer relacionamentos entre classes diferentes, veja por exemplo a classe abaixo, que tem um atributo do "tipo" da classe acima:
class Aparelho:
__pl = None
def __init__(self, pl):
self.__pl = pl
def __del__(self):
del self.__pl
def ligado(self):
if self.__pl.getCarga() > 0: # Getter do objeto Pilha
print(f"O aparelho está ligado e a carga da pilha é de {self.__pl.getCarga()}%!")
else:
print("A pilha do aparelho está sem carga!")
def getPl(self):
return self.__pl
def setPl(self, pl):
self.__pl = pl
Aí podemos chamar os objetos assim:
ray = Pilha("Rayovac")
ray.apresentacao()
controle = Aparelho(ray)
controle.ligado()
print(f"A carga da pilha é de {controle.getPl().getCarga()}%!")