Middle
Em que situações a herança na programação orientada a objetos é útil e em que casos deve ser evitada?
sobes.tech IA
Resposta da IA
A herança é útil para:
- Reutilização de código: A funcionalidade comum é colocada numa classe base.
- Criação de hierarquias de tipos (relação is-a): Quando uma classe filha é uma variação da classe pai.
- Polimorfismo: A capacidade de tratar objetos de diferentes tipos através de uma interface comum da classe base.
- Extensão de funcionalidades: Adicionar novos métodos ou campos a uma classe existente.
Deve evitar-se a herança quando:
- O princípio de substituição de Liskov é violado: A classe filha não pode substituir completamente a classe base sem alterar a correção do programa.
- Cria-se uma ligação rígida entre classes: As alterações na classe base podem afetar indesejadamente todas as classes filhas.
- É necessário combinar funcionalidades de fontes não relacionadas (relação has-a): É melhor usar composição.
- Complexidade excessiva na hierarquia: Cadeias profundas de herança são difíceis de manter e compreender.
- Herança para reutilização de código quando a funcionalidade não é um "tipo" comum: É melhor usar classes utilitárias ou delegação.
// Exemplo, quando a herança é útil
open class Animal {
open fun makeSound() {
println("Som genérico de animal")
}
}
class Dog : Animal() { // Dog É-UMA Animal
override fun makeSound() {
println("Au au")
}
}
class Cat : Animal() { // Cat É-UMA Animal
override fun makeSound() {
println("Miau")
}
}
// Exemplo, quando a composição é preferível à herança para a relação "has-a"
class Engine {
fun start() { println("Motor iniciado") }
}
// Em vez de herdar de Engine para Car
// class Car : Engine() // Má conceção, Car NÃO É-UMA Engine
class Car {
private val engine = Engine() // Car TEM-UMA Engine
fun drive() {
engine.start()
println("Carro a conduzir")
}
}