Olá,
seja bem-vindo/a!
Disciplina: Linguagem de Programação
Prof: Alyson Trindade Fernandes
www.ifnmg.edu.br/diamantina
CLASSES E OBJETOS
● Classe: Um modelo que define os atributos e comportamentos de
objetos. É como um projeto para criar objetos.
● Objeto: Uma instância específica de uma classe que possui seus
próprios valores para os atributos e pode executar os métodos definidos
na classe.
SINTAXE BÁSICA DE CLASSES
class Conta:
def __init__(self, numero, titular, saldo, limite):
self.numer = numero
self.titular = titular
self.saldo = saldo
self.limite = limite
__init__() - CONSTRUTOR
É o método __init__() que vai inicializar os atributos de um objeto. Seu
primeiro parâmetro, assim como todo método de instância, é a própria
instância. Por convenção, chamamos este argumento de self.
INSTÂNCIAS
São construções de objetos a partir de uma classe. Para definir um novo
objeto conta a partir da classe Conta siga esta sintaxe:
from conta import Conta
conta1 = Conta('123-4', 'João', 120.0, 1000.0)
MÉTODOS
Além dos atributos, nossa conta deve possuir funcionalidades.
Para criar o método deposita() na classe Conta, assim como o método
__init__() , deposita() deve receber a instância do objeto (self) além do
valor a ser depositado:
class Conta:
# método __init__() omitido
def deposita(self, valor):
self.saldo += valor
MÉTODOS
Para utilizar o método de uma classe deve-se chamá-lo a partir da
referência de um objeto:
conta1.deposita(20.0)
MÉTODOS COM RETORNO
Um método pode retornar um valor para a sua chamada:
def saca(self, valor):
if (self.saldo < valor):
return False
else:
self.saldo -= valor
return True
MÉTODOS COM RETORNO
Exemplo de uso:
minha_conta.saldo = 1000
consegui = minha_conta.saca(2000)
if(consegui):
print(“consegui sacar”)
else:
print(“não consegui sacar”)
OBJETOS SÃO ACESSADOS POR
REFERÊNCIA
Quando criamos uma variável para associar a um objeto, na verdade,
essa variável não guarda o objeto, e sim uma maneira de acessá-lo,
chamada de referência (o self). Podemos definir a referência de um objeto
como sendo o endereço inicial da memória ram onde este objeto está
armazenado.
c1 = Conta()
c1 guarda o endereço da nova instância da classe conta.
OBJETOS SÃO ACESSADOS POR
REFERÊNCIA
COMUNICAÇÃO ENTRE OBJETOS
O método transfere, lista abaixo, mostra a comunicação entre objetos
inserindo a referência de um objeto como parâmetro do método de outro
objeto. Assim os atributos do objeto passado como referência podem ser
acessados pelo objeto chamador do método.
class Conta:
# código omitido
def transfere(self, destino, valor):
retirou = self.saca(valor)
if (retirou == False):
return False
else:
destino.deposita(valor)
return True
ATRIBUTOS COM VALOR PADRÃO
No exemplo abaixo, o atributo limite possui valor padrão definido no
construtor. Portanto ele não necessita obrigatoriamente ser definido na
instanciação de um novo objeto.
class Conta:
def __init__(self, numero, titular, saldo,
limite=1000.0):
self.numero = numero
self.titular = titular
self.saldo = saldo
self.limite = limite
ATRIBUTOS COM VALOR PADRÃO
Veja que agora não somos obrigados a passar o valor do limite já que ele
possui um valor padrão
de 1000.0
conta = Conta('123-4', 'joão', 120.0)
TUDO É OBJETO
Python é uma linguagem totalmente orientada a objetos. Tudo em Python
é um objeto!
print(type(conta.numero))
#<class 'str'>
print(type(conta.saldo))
#<class 'float'>
print(type(conta.titular))
#<class '__conta__.Cliente'>
MÉTODOS MÁGICOS
Caso você queira saber quais são todos os métodos implementados pela
classe Conta , você pode usar a função embutida dir(), que irá listar todos
métodos e atributos que a classe possui.
dir(Conta)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__',
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__',
'__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__',
'__str__', '__subclasshook__', '__weakref__', 'extrato', 'deposita', 'limite' ,
'numero', 'saca', 'saldo', 'transfere_para', 'titular']
MÉTODOS MÁGICOS
Um outro atributo bastante útil é o __dict__ , que retorna um
dicionário com os atributos da classe.
cliente = Cliente('João', 'Oliveira', '111111111-11')
conta = Conta('123-4', cliente, 1000.0)
print(conta.__dict__)
#{'saldo': 1000.0, 'numero': '123-4', 'titular':
#<__main__.Cliente object at 0x7
#f0b6d028f28>, 'limite': 1000.0}
MODIFICADORES DE ACESSO E
MÉTODOS DE CLASSE
Em linguagens orientadas a objetos devemos esconder os atributos e
métodos que não devem ser acessados por outros sistemas.
Chamamos esta ação de “modificador de acesso”.
Outras linguagens possuem o termo private.
Em python temos algumas alternativas.
A primeira delas é adicionar dois underscores __ antes do nome do
atributo que deve ser privado. Desta forma o atributo fica escondido do
acesso direto
class Pessoa:
def __init__(self, idade):
self.__idade = idade
MODIFICADORES DE ACESSO E
MÉTODOS DE CLASSE
Os atributos com __ no nome ainda podem ser acessados por:
p._Pessoa__idade
Ao colocar o prefixo __ no atributo da classe, o Python apenas renomeia
'__nome_do_atributo' para '_nomeda_Classe_nome_do_atributo', como
fez em __idade para _Pessoa__idade.
Muitos programadores Python não gostam dessa sintaxe e preferem usar
apenas um underscore '_' para indicar quando um atributo deve ser
protegido.
MODIFICADORES DE ACESSO E
MÉTODOS DE CLASSE
As mesmas regras de acesso aos atributos valem para os métodos.
É muito comum, e faz todo sentido, que seus atributos sejam privados e
quase todos seus métodos sejam públicos.
ENCAPSULAMENTO
Encapsular é fundamental para que seu sistema seja suscetível a
mudanças: não precisamos mudar uma regra de negócio em vários
lugares, mas sim em apenas um único lugar, já que essa regra está
encapsulada.
O conjunto de métodos públicos de uma classe é também chamado de
interface da classe, pois esta é a única maneira a qual você se comunica
com objetos dessa classe.
ENCAPSULAMENTO
Outra forma de encapsular os atributos de uma classe é através da
construção de 2 métodos (get e set) para cada atributo.
Getters e setters são usados em muitas linguagens de programação
orientada a objetos para garantir o princípio do encapsulamento de dados.
O encapsulamento de dados é visto como o agrupamento de dados com
os métodos que operam nesses dados.
ENCAPSULAMENTO
class Conta:
def __init__(self, titular, saldo):
self._titular = titular
self._saldo = saldo
def get_saldo(self):
return self._saldo
def set_saldo(self, saldo):
self._saldo = saldo
def get_titular(self):
return self._titular
def set_titular(self, titular):
self._titular = titular
ENCAPSULAMENTO
A forma pythônica de encapsulamento de atributos é diferente:
ENCAPSULAMENTO
class Conta:
def __init__(self, saldo=0.0):
self.saldo = saldo
@property
def saldo(self):
return self.saldo
@saldo.setter
def saldo(self, saldo):
if(saldo < 0):
print("saldo não pode ser negativo")
else:
self.saldo = saldo
ENCAPSULAMENTO
Um método que é usado para obter um valor (o getter) é decorado com
@property , isto é, colocamos essa linha diretamente acima da declaração
do método que recebe o nome do próprio atributo.
O método que tem que funcionar como setter é decorado com
@saldo.setter . Se a função tivesse sido chamada de "func", teríamos que
anotá-la com @func.setter .
ENCAPSULAMENTO
Desta maneira, podemos chamar esses métodos sem os parênteses,
como se fossem atributos públicos. É uma forma mais elegante de
encapsular nossos atributos. Vamos testar criar uma conta e depois
atribuir um valor negativo ao saldo:
conta = Conta(1000.0)
conta.saldo = -300.0
"saldo não pode ser negativo"
ENCAPSULAMENTO
A forma pythônica é bem mais amigável ao usar o encapsulamento. Veja a
diferença dos da chamada dos dois métodos:
Java:
conta3.set_saldo(conta1.get_saldo() + conta2.get_saldo())
Python:
conta3.saldo = conta1.saldo + conta2.saldo
ATRIBUTOS DE CLASSE
● Variável própria da classe, sendo única e compartilhada por todos os
objetos da mesma. Dessa maneira, quando a mesma fosse mudada
através de um objeto, o outro enxergaria o mesmo valor
>>>
class Conta:
_total_contas = 0
def__init__(self, saldo):
self._saldo = saldo
Conta._total_contas += 1
ATRIBUTOS DE CLASSE
c1 = Conta(100.0)
print(c1._total_contas)
#1
c2 = Conta(200.0)
print(c2._total_contas)
#2
ATRIBUTOS DE CLASSE
Também é possível acessar este atributo direto da classe:
>>> Conta._total_contas
MÉTODOS ESTÁTICOS
Métodos estáticos não precisam de uma referência, não
recebem um primeiro argumento especial (self). É como uma
função simples que, por acaso, reside no corpo de uma classe em
vez de ser definida no nível do módulo.
>>>
@staticmethod
def get_total_contas():
return Conta._total_contas
MÉTODOS DE CLASSE
Métodos de classe servem para definir um método que opera na
classe, e não em instâncias. Já os métodosestáticos utilizamos
quando não precisamos receber a referência de um objeto especial
(seja da classe ou de uma instância) e funciona como uma função
comum, sem relação.
Um método de classe pode mudar a implementação, ou seja, pode
ser reescrito pela classe filha. Já os métodos estáticos não
podem ser reescritos pelas filhas, já que são imutáveis e não dependem
de um referência especial.
MÉTODOS DE CLASSE
class Conta:
_total_contas = 0
def __init__(self):
Conta._total_contas += 1
@classmethod
def get_total_contas(cls):
return cls._total_contas
PROTEÇÃO DE CLASSES COM SLOTS
Como Python é uma linguagem dinâmica, nada impede que usuários
de nossa classe Conta criem atributos em tempo de execução,
fazendo, por exemplo:
>>> conta.nome = "minhaconta"
PROTEÇÃO DE CLASSES COM SLOTS
Podemos utilizar uma variável embutida no Python chamada
__slots__ , que pode guardar uma lista de atributos definidos por
nós e garantir que novos atributos não sejam adicionados às instâncias
desta classe.
PROTEÇÃO DE CLASSES COM SLOTS
class Conta:
__slots__ = ['_numero', '_titular', '_saldo', '_limite']
def__init__(self, numero, titular, saldo,
limite=1000.0):
# inicialização dosatributos
>>> conta.nome = "minha_conta" #gera erro
EXERCÍCIO DE FIXAÇÃO
1) Crie uma classe Tempo com três atributos: horas, minutos e segundos.
Crie os seguintes métodos:
a) Construtor para inicializar os atributos com valores passados como
argumentos ou com valores padrão para a hora “00:00:00”;
b) Funcionar como getter e setter;
c) Imprimir os atributos no formato hh:mm:ss;
d) Crie uma classe de teste que cria um objeto Tempo e o inicializa com
a hora do dia;
e) Avançar ou atrasar o tempo de acordo com a hora de outro objeto
Tempo recebida como parâmetro;
f) Um método estático que verifica se um objeto de Tempo possui hora
válida;
g) Um método de classe que retorna a diferença de tempo entre 2
objetos Tempos recebidos como parâmetro;
h) Teste todos os métodos.
EXERCÍCIO DE FIXAÇÃO
1) Crie uma classe Calculadora com quatro atributos: operando_1,
operação, operando_2 e resultado. Crie os seguintes métodos:
a) Construtor para inicializar os atributos com valores passados como
argumentos ou com valores padrão para a operação: 0+0==0;
b) Funcionar como getter e setter;
c) Imprimir os atributos no formato “00+00=00”;
d) Método Estático validar_operacao() que recebe uma string como
parâmetro e verifica se é uma operação válida (+, -, *, /);
e) Método de classe que recebe uma operação no formato “00+00=00” e
extrai os dados da operação e alimenta os atributos da classe;
f) Realizar o cálculo com base nos atributos do objeto;
g) Retornar se a operação setada em um objeto irá gerar divisão por
zero;
h) Teste todos os métodos.
HERANÇA E POLIMORFISMO
…
HERANÇA E POLIMORFISMO
…
HERANÇA E POLIMORFISMO
…
HERANÇA E POLIMORFISMO (REESCRITA DE
MÉTODOS)
HERANÇA E POLIMORFISMO (REESCRITA DE
MÉTODOS)
HERANÇA E POLIMORFISMO (REESCRITA DE
MÉTODOS)
HERANÇA E POLIMORFISMO
Polimorfismo é a capacidade de um objeto poder ser
referenciado de várias formas (cuidado, polimorfismo não
quer dizer que o objeto fica se transformando, muito pelo
contrário, um objeto nasce de um tipo e morre daquele tipo, o
que pode mudar é a maneira como nos referimos a ele).
HERANÇA E POLIMORFISMO
HERANÇA E POLIMORFISMO
…
HERANÇA E POLIMORFISMO
● No dia em que criarmos uma classe Secretaria , por exemplo, que é filha
de Funcionario, precisaremos mudar a classe ControleDeBonificacoes ?
● O quê acontece se tentarmos registrar um cliente na classe
ControleDeBonificacoes ? Faça o teste.
HERANÇA E POLIMORFISMO
…
HERANÇA E POLIMORFISMO
…
HERANÇA E POLIMORFISMO
Você deve escrever o código esperando somente uma interface do objeto,
não um tipo de objeto.
No caso da nossa classe ControleDeBonificacoes , o método registra()
espera um objeto que possua o método get_bonificacao() e não apenas
um funcionário.
HERANÇA E POLIMORFISMO
O Duck Typing é um estilo de programação que não
procura o tipo do objeto para determinar se ele tem a
interface correta. Ao invés disso, o método ou atributo é
simplesmente chamado ou usado ('se parece como um
pato e grasna como um pato, então deve ser um pato').
HERANÇA E POLIMORFISMO
O que é importante é que a maneira pythônica de se fazer é assumir a
existência do atributo e capturar (tratar) um exceção quando o atributo não
pertencer ao objeto e seguir o fluxo do programa.
CLASSES ABSTRATAS
Neste sistema, não faz sentido instanciar um objeto da classe
Funcionario.
Logo, a classe Funcionario é uma classe abstrata. Ela serve de molde
(rascunho) para a construção de outras classes.
Uma classe abstrata não pode ser instanciada e deve conter pelo menos
um método abstrato.
CLASSES ABSTRATAS
…
CLASSES ABSTRATAS
Uma classe abstrata não pode ter um método instanciado;
É possível instanciar um objeto de uma classe filha da classe abstrata;
Não é possível herdar de uma classe abstrata sem instanciar todos os
seus métodos abstratos;
Métodos abstratos não possuem implementação na classe base e devem
ser implementados nas classe subclasses;
CLASSES ABSTRATAS
…
CLASSES ABSTRATAS
…
CLASSES ABSTRATAS
…
CLASSES ABSTRATAS
…
CLASSES ABSTRATAS
…
CLASSES ABSTRATAS
…
CLASSES ABSTRATAS
…
CLASSES ABSTRATAS
…
CLASSES ABSTRATAS
…
CLASSES ABSTRATAS
…
CLASSES ABSTRATAS
…
OBRIGADO!
Esperamos que você consiga
desenvolver todo seu potencial
conosco.