| | | | |

7.2 Herança

Compre o e-book deste material aqui!

Na programação orientada-a-objetos, herança consiste na definição de uma classe derivada a partir de uma dada classe base. A sintaxe de definição de uma classe derivada é

1class ClasseDerivada(ClasseBase):
2  bloco-0
3  bloco-1
4  ...
5  bloco-n

A classe derivada herda todos os atributos da classe base. Por exemplo, consideramos o seguinte código

1class ClasseBase:
2  def __init__(self, nome):
3    self.nome = nome
4
5  def digaOi(self):
6    print(f'{self.nome}: Oi!')
7
8class ClasseDerivada(ClasseBase):
9  def digaTchau(self):
10    print(f'{self.nome}: Tchau!')
11
12obj = ClasseDerivada('Fulane')
13obj.digaOi()
14obj.digaTchau()

Nas linhas 1-6, a classe base é definida contendo dois métodos: __init__() chamado na criação de um objeto da classe (uma instância) e, self.digaOi() que imprime uma saudação. A classe derivada é definida nas linhas 8-10, ela herda os atributos da classe base e contém um novo método self.digaTchau(), que imprime uma mensagem de despedida.

A criação de uma instância (objeto) de uma classe derivada é feita da mesma forma que de uma classe base. A referência a um atributo do objeto é, primeiramente, buscada na classe derivada e, se não encontrada, é buscada na classe base. Este regra aplica-se recursivamente se a classe base também é derivada de outra classe. Isso permite que uma classe derivada sobreponha atributos de sua classe base.

Observação 7.2.1.

(super().) O método super retorna um objeto proxy da classe base, que acessa os atributos desta.

Exemplo 7.2.1.

Vamos criar uma classe para manipular triângulo isósceles. Para tanto, vamos derivá-la a partir da classe Triangulo definida no Exemplo 7.1.1. Vamos assumir que os triângulos isósceles têm vértices ΔABC com lados b=AC e a=BC de mesmo tamanho.

Código 12: classTrianguloIsosceles.py
1import numpy as np
2import matplotlib.pyplot as plt
3
4class Triangulo:
5  '''
6  Classe Triangulo ABC.
7  '''
8  num_lados = 3
9  def __init__(self, A, B, C):
10    # vértices
11    self.A = A
12    self.B = B
13    self.C = C
14
15  def plot(self):
16    fig = plt.figure()
17    ax = fig.add_subplot()
18    # lados
19    ax.plot([self.A[0], self.B[0]],
20            [self.A[1], self.B[1]], marker='o', color='blue')
21    ax.text((self.A[0]+self.B[0])/2,
22            (self.A[1]+self.B[1])/2, 'c')
23    ax.plot([self.B[0], self.C[0]],
24            [self.B[1], self.C[1]], marker='o', color='blue')
25    ax.text((self.B[0]+self.C[0])/2,
26            (self.B[1]+self.C[1])/2, 'a')
27    ax.plot([self.C[0], self.A[0]],
28            [self.C[1], self.A[1]], marker='o', color='blue')
29    ax.text((self.A[0]+self.C[0])/2,
30            (self.A[1]+self.C[1])/2, 'b')
31    # vertices
32    ax.text(self.A[0], self.A[1], 'A')
33    ax.text(self.B[0], self.B[1], 'B')
34    ax.text(self.C[0], self.C[1], 'C')
35    ax.grid()
36    plt.show()
37
38
39class TrianguloIsosceles(Triangulo):
40  def __init__(self,A,B,C):
41    # vertices
42    super().__init__(A,B,C)
43    # lados
44    self.a = self.b = self.c = 0.
45
46  def calcLados(self):
47    self.a = np.sqrt((self.B[0] - self.C[0])**2\
48                      + (self.B[1] - self.C[1])**2)
49    self.b = np.sqrt((self.A[0] - self.C[0])**2\
50                      + (self.A[1] - self.C[1])**2)
51    self.c = np.sqrt((self.B[0] - self.A[0])**2\
52                      + (self.B[1] - self.A[1])**2)
53    assert(self.a == self.b)
54
55tria = TrianguloIsosceles((1,0),
56                          (3,0),
57                          (2,1))
58tria.plot()
59tria.calcLados()
Observação 7.2.2.

(Herança Múltipla.) Python suporta a herança múltipla de classes. A sintaxe é

1class ClasseDerivada(Base1, Base2, ..., BraseN):
2  bloco-0
3  bloco-1
4  ...
5  bloco-m

Quando um objeto da classe derivada faz uma referência a um atributo, este é procurado de forma sequencial (e recursiva, caso uma das classe bases seja também uma classe derivada) começando por essa e, caso não encontrado, buscando-se nas classes Base1, Base2, …, BaseN.

7.2.1 Exercícios

E. 7.2.1.

No Código 12, adicione à classe Triangulo o método Triangulo.perimetro() que computa, aloca e retorna o valor do perímetro do triângulo. Então, sobreponha o método à classe TrianguloIsosceles. Teste seu código para diferentes triângulos.

Resposta.
1class Triangulo:
2  def __init(self,A,B,C)__:
3    ...
4    self.p = 0.
5    ...
6  ...
7  def perimetro(self):
8    self.p = self.a\
9            + self.b\
10            + self.c
11    return self.p
12  ...
13
14class TrianguloIsosceles(Triangulo):
15  ...
16  def perimetro(self):
17    self.p = 2*self.a + self.c
18    return self.p
19  ...
E. 7.2.2.

Implemente uma classe Retangulo(largura, altura) para a manipulação de retângulos de largura e altura dadas. Equipe sua classe com métodos para o cálculo do perímetro, da diagonal e da área de retângulo. Então, implemente a classe derivada Quadrado(lado) para a manipulação de quadrados de lado dado. Teste sua implementação para diferentes retângulos e quadrados.

Resposta.
1import math as m
2
3class Retangulo:
4  def __init__(self, largura, altura):
5    self.largura = largura
6    self.altura = altura
7
8  def perimetro(self):
9    return self.largura\
10            + self.altura
11
12  def diagonal(self):
13    return m.sqrt(self.largura**2\
14                  + self.altura**2)
15
16  def area(self):
17    return self.largura\
18            * self.altura
19
20class Quadrado(Retangulo):
21  def __init__(self,lado):
22    super().__init__(lado,lado)
E. 7.2.3.

Refaça o Exercício 7.2.2 sobrepondo os métodos do cálculo do perímetro, da diagonal e da área para quadrados.

Resposta.

Dica: para um quadrado de lado l, o perímetro é p=2l, por exemplo.

E. 7.2.4.

Considere a classe TrianguloIsosceles definida no Código 12. Implemente uma classe derivada TrianguloEquilatero com métodos para o cálculo do perímetro e da altura de triângulo equiláteros. Teste seu código para diferentes triângulos.

Resposta.

Dica:

1...
2class Triangulo:
3  def __init__(self,A,B,C):
4    ...
5  ...
6
7class TrianguloIsosceles(Triangulo):
8   ...
9
10class TrianguloEquilatero(TrianguloIsosceles):
11  def __init__(self,A,B,C):
12    super().__init__(A,B,C)
13
14  def perimetro(self):
15    ...
16
17  def altura(self):
18    ...
19
20  def area(self):
21    ...
E. 7.2.5.

Implemente:

  1. a)

    Uma classe Quadrilatero para a manipulação de quadriláteros de lados abcd. Equipe sua classe com um método self.perimetro() para o cálculo do perímetro.

  2. b)

    Uma classe Retangulo, derivada da classe Quadrilatero, para a manipulação de retângulos de lado dado e altura dada. Na classe derivada, sobreponha o método self.perimetro() para o cálculo do perímetro e implemente novos métodos para o cálculo da diagonal e da área de retângulos.

  3. c)

    Uma classe Quadrado, derivada da classe Retangulo, para a manipulação de quadrados de lado dado. Na classe derivada, sobreponha os métodos para os cálculos do perímetro, da diagonal e da área.


Envie seu comentário

As informações preenchidas são enviadas por e-mail para o desenvolvedor do site e tratadas de forma privada. Consulte a Política de Uso de Dados para mais informações. Aproveito para agradecer a todas/os que de forma assídua ou esporádica contribuem enviando correções, sugestões e críticas!