| | | |

Algoritmos e Programação I

7 Orientação a objetos

Material disponível para compra: e-book apostila. Consulte outras formas de colaboração aqui!

7.2 Herança

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


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.


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 E.7.2.2 sobrepondo os métodos do cálculo do perímetro, da diagonal e da área para quadrados.


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.


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

Aproveito para agradecer a todas/os que de forma assídua ou esporádica contribuem enviando correções, sugestões e críticas!

Opcional. Preencha seu nome para que eu possa lhe contatar.
Opcional. Preencha seu e-mail para que eu possa lhe contatar.
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.

Licença Creative Commons
Este texto é disponibilizado nos termos da Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional. Ícones e elementos gráficos podem estar sujeitos a condições adicionais.

Pedro H A Konzen
| | | |