Fundamentos da Programação
Capítulo 11: Programação com objetos
Classes e instâncias
Classes, subclasses e herança• Vantagens da programação com objetos é a possibilidade de construir
entidades reutilizáveis• Componentes que podem ser usados em programas diferentes através da
especialização para necessidades específicas
• Os bancos oferecem diferentes tipos de contas• Contas ordenado que permitem apresentar saldos negativos (até um certo
limite)• Contas jovem que não permitem saldos negativos, mas que não impõem
restrições mínimas para o saldo de abertura
Classes, subclasses e herança• Todas as contas são “contas bancárias” com caraterísticas que variam
de conta para conta• A programação tradicional levaria à criação de funções muito semelhantes
mas refletindo as operações específicas a cada tipo de conta• Em programação com objetos, a abordagem seguida corresponde à criação
de classes que especializam outras classes
Classes, subclasses e herança• Classe de contas genéricas, conta_gen, a qual sabe efetuar
levantamentos, depósitos e consultas ao saldo. Esta classe tem duas variáveis de estado saldo e self.saldo_min
Classes, subclasses e herança• Queremos criar os seguintes tipos de contas• Conta ordenado: está associada à transferência mensal do ordenado
do seu titular e está sujeita às seguintes condições• a abertura exige um saldo mínimo igual ao valor do ordenado a ser transferido
para a conta• permite saldos negativos, até um montante igual ao ordenado
• Conta jovem: conta feita especialmente para jovens e que está sujeita às seguintes condições:
• a abertura não exige um saldo mínimo• não permite saldos negativos
Classes, subclasses e herança• Podemos pensar em duplicar o código associado à classe conta_gen,
fazendo as adaptações necessárias nos respetivos métodos• Má prática de programação
• Aumenta desnecessariamente a quantidade de código• Qualquer alteração realizada sobre conta_gen não se propaga
às classes conta_ordenado e conta_jovem, as quais são contas
Classes, subclasses e herança• Em programação com objetos existe o conceito de subclasse
• Uma classe é uma subclasse de outra, se a primeira for uma especialização da segunda
• O comportamento da subclasse corresponde ao comportamento da superclasse, exceto no caso em que um comportamento específico está indicado para a subclasse
• A subclasse herda o comportamento da superclasse, exceto quando este é explicitamente alterado na subclasse
Classes, subclasses e herança
• Uma definição de classe da forma class < nome1> () estabelece a classe como uma subclasse de
• A classe “herda” automaticamente todas as variáveis e métodos definidos na classe
Classes, subclasses e herança• Definindo a classe conta_ordenado como
conta_ordenado(conta_gen)
• Se nada for dito em contrário, conta_ordenado passa a ter os métodos deposito, levantamento e consulta de conta_gen
• Se em conta_ordenado, for definido um método com o mesmo nome de conta_gen, este método, na classe conta_ordenado, sobrepõe-se ao método homónimo da classe conta_gen
• Se forem definidos novos métodos em conta_ordenado, estes pertencem apenas a conta_ordenado, não existindo na conta_gen
Classes, subclasses e herança• As classes podem ter subclasses que correspondem a especializações
dos seus elementos• As subclasses herdam as variáveis de estado e os métodos das
superclasses, salvo indicação em contrário
Classes, subclasses e herança
Classes, subclasses e herança
Classes, subclasses e herança
Classes, subclasses e herança
Conta com PIN – versão 1• Queremos proteger uma conta bancária por um código de segurança,
conhecido por PIN• Uma proteção através de um PIN existe nas máquinas Multibanco, nos
telemóveis e numa grande quantidade de situações
• Definir o comportamento de uma entidade com PIN, obj_com_pin, dentro da qual existe uma entidade de qualquer tipo
• Caraterizada por variáveis de estado correspondentes ao PIN, a um contador de acessos incorretos e ao objeto protegido pelo PIN
Conta com PIN – versão 1class obj_com_pin:
def __init__(self, pin, obj):self.pin = pinself.contador = 0self.obj = obj
def acede(self, pin):if self.contador == 3:
print('Conta bloqueada')elif pin == self.pin:
self.contador = 0return self.obj
else:self.contador = self.contador + 1 if self.contador == 3:
print('Conta bloqueada')else:
print('PIN incorrecto')mensagem = 'Tem mais ‘ +\
str(3-self.contador) +\' tentativas'
print(mensagem)
def altera_PIN(self, pin): if self.verifica_PIN(pin):
novopin = input('Introduza o novo PIN\n--> ‘)print('Para verificação')verifica = input('Volte a introduzir o novo PIN\n--> ')
if novopin == verifica:self.pin = novopinprint('PIN alterado')
else:print('Operação sem sucesso')
Conta com PIN – versão 1>>> conta = obj_com_pin('ABC', conta_jovem(100))>>> conta.acede('ABC').consulta()100>>> conta.acede('ABC').levantamento(50)50>>> conta.acede('XPTO').consulta()PIN incorretoTem mais 2 tentativas>>> conta.altera_PIN('ABC')Introduza o novo PIN--> XPTOPara verificaçãoVolte a introduzir o novo PIN--> XPTOPIN alterado>>> conta.acede('XPTO').consulta()50
Conta com PIN – versão 2• Alternativa para definir obj_com_pin
• Não a criar o objeto protegido pelo PIN como um argumento do método que cria a instância
• Criá-lo durante a inicialização das variáveis de estado da instância
• Fornecer ao método __init__ o nome da classe correspondente ao objeto a criar e os argumentos necessários para a criação desse objeto
• Exige que instâncias de diferentes classes podem ter que ser criadas com diferente número de argumentos
• Recorrer à utilização de funções com um número arbitrário de argumentos
Conta com PIN – versão 2
Objetos em Python• O Python é uma linguagem baseada em objetos
• A nossa utilização do Python correspondeu à sua faceta imperativa• Todos os tipos de dados embutidos em Python correspondem a classes
>>> type(2)
>>> type(True)
>>> type(3.5)
>>> type('abc’)
>>> type([1, 2, 3])
Polimorfismo• Muitas das operações do Python são sobrecarregadas, aplicam-se a
vários tipos de dados. Por exemplo, + pode ser aplicada a inteiros, a reais, a tuplos, a cadeias de caracteres e a listas
• Uma operação diz-se polimórfica quando é possível definir funções diferentes que usam a mesma representação externa da operação para lidar com tipos de dados diferentes
• Após definirmos a classe complexo estaremos interessados em escrever funções que executem operações aritméticas sobre complexos. A soma de complexos pode ser definida por
def soma_compl(c1, c2):
return compl(c1.p_real() + c2.p_real(), c1.p_imag() + c2.p_imag())
Polimorfismo• Permite a interação
>>> c1 = compl(9, 6)>>> c2 = compl(7, 6)>>> c3 = soma_compl(c1, c2)>>> c3.escreve()16 + 12 i
• Quando trabalhamos complexos em Matemática usamos o símbolo + para representar a soma complexos
• Através do polimorfismo, o Python permite especificar que a operação +também pode ser aplicada complexos e instruir o computador em como aplicar a operação + a números complexos
Polimorfismo• Em Python todos os tipos embutidos correspondem a classes
• Um dos métodos que existe numa classe tem o nome de __add__, recebendo dois argumentos, self e outro elemento do mesmo tipo
>>> a = 5>>> a.__add__(2)7
• A invocação deste método pode ser feita através da representação externa +
• Sempre que o Python encontra a operação +, invoca o método __add__, aplicado às instâncias envolvidas
Polimorfismo• Se na classe compl, definirmos o métododef __add__(self, outro):
return compl(self.p_real() + outro.p_real(), \self.p_imag() + outro.p_imag())
• Podemos originar a interação>>> c1 = compl(2, 4)>>> c2 = compl(5, 10)>>> c3 = c1 + c2>>> c3.escreve()7 + 14i
PolimorfismoExistem métodos embutidos, com os nomes
__sub____mul____truediv____eq__
associados às representações das operações -, *, /, ==
O método __repr__ transforma a representação interna de uma instância numa cadeia de caracteres que corresponde à representação externa
Polimorfismo>>> c1 = compl(2, 5)>>> c12+5i>>> c2 = compl(-9, -7)>>> c2-9-7i>>> c1 + c2-7-2i>>> c1 * c217-59i>>> c1 == c2False>>> c4 = compl(2, 5)>>> c1 == c4True