Enviar um café pro programador

Como Usar Herança em Python

Neste tutorial, vamos de fato colocar a mão na massa e aprender a usar o conceito de herança em Python, fazendo uma classe herdar outra.

Baixe nossa apostila: Python Progressivo

Como fazer Herança

Vamos supor que temos a classe Veiculo:

class Veiculo:
   #Métodos e atributos
   #da classe veículo

Agora, desejamos criar a classe Carro, que vai herdar a Veiculo, basta colocarmos (Veiculos) entre parêntesis na definição de Carro:

class Carro(Veiculo):
   #Essa classe vai herdar
   #coisas da classe Veiculo

Ou seja, sempre que a classe X for herdar a classe Y, fazemos:
class X(Y):

E prontinho. O que tiver na classe Y (métodos e atributos), vai pra classe X também, sem precisarmos reescrever códigos e mais códigos. Agora, podemos escrever só os códigos específicos da classe X que não tem na Y,


Exemplo de Herança em Python

Vamos lá, criar algum código e ver a herança funcionando na prática.

Primeiro vamos criar a classe Veiculo, que tem os atributos tipo (carro, moto, suv etc), modelo (celta, palio, honda, biz etc) e km que indica a quilometragem do veículo.
Nossa classe fica:

class Veiculo:
 def __init__(self, tipo, modelo, km):
  self.tipo = tipo
  self.modelo = modelo
  self.km = km

Agora vamos a classe Carro, que vai herdar a classe Veiculo.
Ela recebe os atributos tipo, modelo, km e o portas.

Como os três primeiros são da classe base, a Veiculo, basta chamarmos o método __init__ da classe Veiculo passando tais argumentos.

O único parâmetro novo é o portas, pois Carro tem porta, mas nem todo Veiculo tem porta.
Criamos também um novo método, o exibe(), que vai exibir os dados do carro. Veja como ficou nossa classe.

class Carro (Veiculo):
 def __init__(self, tipo, modelo, km, portas):
  Veiculo.__init__(self, tipo, modelo, km)
  self.portas = portas
 
 def exibe(self):
  print(self.tipo, "modelo", self.modelo, "com", self.km, 
     "km rodados e", self.portas, "portas.")

Nosso código completo, criando um objeto do tipo Carro, que é um Palio, de 2 portas e 10.000km rodados:

class Veiculo:
 def __init__(self, tipo, modelo, km):
  self.tipo = tipo
  self.modelo = modelo
  self.km = km
  
class Carro (Veiculo):
 def __init__(self, tipo, modelo, km, portas):
  Veiculo.__init__(self, tipo, modelo, km)
  self.portas = portas
 
 def exibe(self):
  print(self.tipo, "modelo", self.modelo, "com", self.km, 
     "km rodados e", self.portas, "portas.")
  
palio = Carro("Carro", "Palio", "10000", 2)
palio.exibe()

Rode e veja o resultado do código acima.
Note que não declaramos na classe Carro os atributos tipo, modelo e km.
Eles foram herdados automaticamente da classe Veiculo.

Fizemos: self.portas = portas pois esse atributo é novo, existe somente na classe Carro e não tem na Veiculo. Captou a ideia da herança?

Nomenclatura importante:
Veiculo é chamada de superclasse.
Carro é chamada de subclasse.

Note que invocamos o método __init__ da superclasse, para ela iniciar os parâmetros. Fazendo isso, automaticamente inicializa os atributos da subclasse, pois um objeto do tipo Carro é um objeto do tipo Veiculo também.

Tem algo na superclasse? Vai ter na subclasse também, seja método ou atributo.

Exercício de Herança

Adicione uma classe ao script, a Moto.
Ela deve herdar a superclasse Veiculo e deve ter um atributo novo, o cilindrada e ter um método exibe() que printa todas as suas características.

Crie um objeto da subclasse Moto e chame o método exibe() para ver se funcionou.

Sistema bancário com Herança em Python

Vamos agora criar um pequeno sistema bancário em Python, usando herança.

Primeiro, criamos a classe Conta que vai ser a superclasse, o escopo, o esqueleto de toda conta desse banco. Ele tem um atributo, o saldo, que representa o valor na conta e o método getSaldo que retorna esse valor. Ela inicia o saldo com valor nulo.


Depois, criamos a classe PF para representar as contas de pessoas físicas. Ela é subclasse da Conta e tem um método diferente, o setSaldo, que faz a movimentação bancária e cobra cinco reais de cada operação.

Depois, criamos a classe PJ, para pessoas jurídicas, ela é igual a PF, porém seu método setSaldo cobra dez reais de cada operação. Chamamos a superclasse no método __initi__ de ambos tipos de conta, para inicializar o atributo saldo, que é sempre inicialmente 0.

Então, fazemos nosso script rodar. Inicialmente ele vai te perguntar se quer abrir uma conta PF ou PJ, dependendo do que o usuário escolher, instanciamos um objeto da classe PF ou PJ.

Depois, em um looping infinito (um caixa eletrônico que funciona pra sempre), pergunta se você deseja ver o saldo ou fazer uma movimentação.

Para ver, basta chamar o método getSaldo do objeto conta.
Para sacar, basta fornecer um valor negativo e para depositar, um valor positivo.

Note que se for PF, vai ter uma taxa de 5 reais para cada movimentação.
Se for PF, essa taxa é de 10 reais.

Veja nosso script:

class Conta:
 def __init__(self):
  self.saldo = 0
 
 def getSaldo(self):
  return self.saldo
  
class PF (Conta):
 def __init__(self,):
  Conta.__init__(self)
 
 def setSaldo(self, valor):
  self.saldo += valor - 5
  
class PJ (Conta):
 def __init__(self, inicial):
  Conta.__init__(self, inicial)
 
 def setSaldo(self, valor):
  self.saldo += valor - 10


print("1.Criar conta Pessoa Física")
print("2.Criar conta Pessoa Jurídica")
op = int(input("Opção:"))

if op==1:
 conta = PF()
elif op==2:
 conta = PJ()

while True:
 print("1. Ver saldo")
 print("2. Sacar / Depositar")
 op = int(input("Opção:"))
 
 if op == 1:
  print("R$", conta.getSaldo())
 elif op==2:
  val = float(input("Valor para movimentar:"))
  conta.setSaldo(val)
 

Rode ele e brinque um pouco, testando ambos tipos de contas.

4 comentários:

  1. Parametro incial na conta PJ não se faz necessario, causando erro.
    Ou retira o parametro, Ou chama uma função dentro do construtor com self.setSaldo(inicial)

    ResponderExcluir
    Respostas
    1. Eu tentei corrigir a classe PJ e ficou assim o código todo:

      class Conta:
      def __init__(self):
      self.saldo = 0

      def getSaldo(self):
      return self.saldo

      class PF(Conta):
      def __init__(self,):
      Conta.__init__(self)

      def setSaldo(self, valor):
      self.saldo += valor - 5

      class PJ(Conta):
      def __init__(self,inicial):
      Conta.__init__(self,)
      self.saldo = inicial - 10

      def setSaldo(self, valor):
      self.saldo += valor - 10


      print("1. Criar conta pessoa fisica")
      print("2. Criar conta pessoa juridica")
      op = int(input("Opcao: "))

      if op == 1:
      conta = PF()
      elif op == 2:
      conta = PJ(float(input("Valor inicial: ")))

      while True:
      print("1. Ver saldo")
      print("2. Sacar / Depositar")
      op = int(input("Opcao: "))

      if op == 1:
      print("R$", conta.getSaldo())
      elif op == 2:
      val = float(input("Valor para movimentar: "))
      conta.setSaldo(val)

      Excluir
  2. ow obrigada mesmo! finalmente consegui ver como se faz para colocar um parâmetro além da classe-pai. pra ser programador tem que ser pesquisador profissional ne? valeu demais ze

    ResponderExcluir
  3. Dando minha contribuição no código, que tinha o erro na Classe PJ.

    incluir a entrada abaixo no metodo inicial do PJ
    conta = PJ(float(input("Valor inicial: ")))

    E também coloquei a linha abaixo para ele incluir esse valor no saldo inicial e ser demostrado. Se não fizer isso, vc vai passar que esta iniciando com saldo 100, mas se na sequencia chamar o getsaldo, vai mostrar valor R$0, poise ele não estava atribuindo o valor inicial no saldo.

    class Conta:
    def __init__(self):
    self.saldo = 0

    def getSaldo(self):
    return self.saldo

    class PF(Conta):
    def __init__(self, ):
    Conta.__init__(self)

    def setSaldo(self, valor):
    self.saldo += valor - 5

    class PJ(Conta):
    def __init__(self, inicial):
    Conta.__init__(self,)
    self.saldo += inicial

    def setSaldo(self, valor):
    self.saldo += valor - 10

    print("1.Criar conta Pessoa Física")
    print("2.Criar conta Pessoa Jurídica")
    op = int(input("Opção:"))

    if op == 1:
    conta = PF()
    elif op == 2:
    conta = PJ(float(input("Valor inicial: ")))

    while True:
    print("1. Ver saldo")
    print("2. Sacar / Depositar")
    print("0. Sair")
    op = int(input("Opção:"))

    if op == 1:
    print("R$", conta.getSaldo())
    elif op == 2:
    val = float(input("Valor para movimentar:"))
    conta.setSaldo(val)
    elif op ==0:
    break
    else:
    print('Op~ção invalida! ')

    ResponderExcluir