Partilhar: WhatsApp
aulify
UC UC00608 · T. Desenv. Software

Ficha 02 · Herança, polimorfismo, composição

super(), classes abstractas, composição vs herança
Versão · Aluno
Tempo · 60 minutos
Cotação · 100 pontos
Aluno(a)
Turma
Data
Objectivos da ficha

Parte I · Herança

Exercício 1 · Herdar Pessoa (15 pts)

Cria Pessoa(nome, idade) com método saudar(). Cria Aluno(nome, idade, numero) que herda de Pessoa e adiciona método info() que devolve string com tudo.

class Pessoa:
    def __init__(self, nome, idade):
        self.nome = nome
        self.idade = idade

    def saudar(self):
        return f"Olá, sou {self.nome}"

class Aluno(Pessoa):
    def __init__(self, nome, idade, numero):
        super().__init__(nome, idade)
        self.numero = numero

    def info(self):
        return f"{self.nome}, {self.idade} anos, nº {self.numero}"

a = Aluno("Ana", 17, 42)
print(a.saudar())     # herdado
print(a.info())       # próprio

Exercício 2 · isinstance (10 pts)

Considera:

class A: pass
class B(A): pass
class C(B): pass

obj = C()

Indica True ou False:

a) isinstance(obj, C) ___

b) isinstance(obj, B) ___

c) isinstance(obj, A) ___

d) isinstance(obj, object) ___

e) type(obj) is C ___

f) type(obj) is A ___

a) True — é instância de C directamente. b) True — C herda de B. c) True — C herda transitivamente de A. d) True — tudo em Python herda de object. e) True — tipo exacto. f) Falsetype() é exacto, não considera herança.

isinstance() respeita herança; type() is é estrito.

Parte II · Polimorfismo

Exercício 3 · Animais (20 pts)

Cria classe Animal com método som() que retorna "...". Cria 3 subclasses (Cão, Gato, Vaca) que redefinem som(). Escreve função coro(animais) que recebe lista e imprime som de cada.

class Animal:
    def __init__(self, nome):
        self.nome = nome

    def som(self):
        return "..."

    def __repr__(self):
        return f"{type(self).__name__}({self.nome})"

class Cao(Animal):
    def som(self):
        return "Au au!"

class Gato(Animal):
    def som(self):
        return "Miau!"

class Vaca(Animal):
    def som(self):
        return "Muuu!"

def coro(animais):
    for a in animais:
        print(f"{a.nome}: {a.som()}")

coro([
    Cao("Rex"),
    Gato("Mia"),
    Vaca("Mimosa"),
])

Polimorfismo: coro() não precisa de saber o tipo concreto. Cada animal responde à sua maneira.

Exercício 4 · Figuras geométricas (15 pts)

Cria classe abstracta Figura com método abstracto area(). Cria Rectangulo, Circulo, Triangulo. Função area_total(figuras) devolve soma das áreas.

from abc import ABC, abstractmethod
import math

class Figura(ABC):
    @abstractmethod
    def area(self):
        pass

class Rectangulo(Figura):
    def __init__(self, l, a):
        self.l, self.a = l, a
    def area(self):
        return self.l * self.a

class Circulo(Figura):
    def __init__(self, r):
        self.r = r
    def area(self):
        return math.pi * self.r ** 2

class Triangulo(Figura):
    def __init__(self, base, altura):
        self.base = base
        self.altura = altura
    def area(self):
        return self.base * self.altura / 2

def area_total(figuras):
    return sum(f.area() for f in figuras)

figs = [Rectangulo(3, 4), Circulo(5), Triangulo(6, 8)]
print(f"Total: {area_total(figs):.2f}")

Parte III · Composição

Exercício 5 · Carro (15 pts)

Cria classe Motor(cilindrada) com método ligar(). Cria classe Carro(marca, modelo, cilindrada) que contém um Motor. Carro.arrancar() chama motor.ligar().

class Motor:
    def __init__(self, cilindrada):
        self.cilindrada = cilindrada
        self.ligado = False

    def ligar(self):
        self.ligado = True
        return f"Motor {self.cilindrada}cc ligado"

class Carro:
    def __init__(self, marca, modelo, cilindrada):
        self.marca = marca
        self.modelo = modelo
        self.motor = Motor(cilindrada)   # composição: Carro TEM Motor

    def arrancar(self):
        return self.motor.ligar()

c = Carro("Toyota", "Corolla", 1800)
print(c.arrancar())
print(c.motor.ligado)

Exercício 6 · Herança vs composição (15 pts)

Para cada caso, decide se modelarias com herança ou composição e justifica em 1 frase:

a) Aluno e Pessoa. ___

b) Carro e Motor. ___

c) Lobo e Animal. ___

d) Equipa e Jogador. ___

e) Livro e Editora. ___

f) Quadrado e Rectangulo (matematicamente). ___

a) Herança — Aluno é uma Pessoa.

b) Composição — Carro tem um Motor (não é um motor).

c) Herança — Lobo é um Animal.

d) Composição — Equipa tem jogadores (lista de Jogador).

e) Composição — Livro tem uma editora; livro não é editora.

f) Cuidado. Matematicamente Quadrado é Rectangulo, mas em código viola LSP — mudar largura de Quadrado teria de mudar altura. Melhor: ambos herdam de Figura, sem herança entre si. Composição (Quadrado tem propriedade lado) também válida.

Parte IV · Cenário

Exercício 7 · Sistema de empréstimo (10 pts)

Modela uma biblioteca: - ItemBiblioteca (abstracta) com método info() abstracto. - Livro(titulo, autor) herda. - Revista(titulo, edicao) herda. - Biblioteca que tem lista de itens (composição) e métodos adicionar(item), listar().

from abc import ABC, abstractmethod

class ItemBiblioteca(ABC):
    @abstractmethod
    def info(self):
        pass

class Livro(ItemBiblioteca):
    def __init__(self, titulo, autor):
        self.titulo = titulo
        self.autor = autor
    def info(self):
        return f"Livro: '{self.titulo}' por {self.autor}"

class Revista(ItemBiblioteca):
    def __init__(self, titulo, edicao):
        self.titulo = titulo
        self.edicao = edicao
    def info(self):
        return f"Revista: '{self.titulo}' edição {self.edicao}"

class Biblioteca:
    def __init__(self, nome):
        self.nome = nome
        self.itens = []  # composição

    def adicionar(self, item):
        if not isinstance(item, ItemBiblioteca):
            raise TypeError("Tem de ser ItemBiblioteca")
        self.itens.append(item)

    def listar(self):
        print(f"Biblioteca {self.nome}:")
        for item in self.itens:
            print(f"  - {item.info()}")

# Teste
b = Biblioteca("Municipal")
b.adicionar(Livro("Saramago", "Ensaio sobre a cegueira"))
b.adicionar(Livro("Camões", "Lusíadas"))
b.adicionar(Revista("Visão", 1542))
b.listar()

Note como listar() chama item.info() sem se importar do tipo — polimorfismo.