Oi Sabrina,
A composição pode ser utilizada como uma substituição à herança, quando essa não fizer sentido.
Vou dar um exemplo bem tosco, mas que demonstra essa situação :D
Imagine um sistema de uma clinica veterinária no qual você precisou criar uma classe chamada cachorro
:
public class Cachorro {
private String nome;
private LocalDate dataNascimento;
private String raca;
private String cor;
private BigDecimal peso;
}
Agora imagine que a clinica também passou a atender gatos, e você então criou mais uma classe no sistema:
public class Gato {
private String nome;
private LocalDate dataNascimento;
private String raca;
private String cor;
private BigDecimal peso;
}
Repare que as duas classes são idênticas, ou seja, aqui é onde entra a ideia de utilizar herança, para reaproveitar código:
public class Gato extends Cachorro {
}
Mas será que a herança faz sentido? Aqui é bem evidente que não, pois de cara já pensaríamos que realmente um gato não é um cachorro :D Mas em outras situações nem sempre isso é fácil de identificar.
A herança aqui seria usada apenas por "preguiça", para reaproveitar os atributos iguais e evitar ter que duplica-los. Mas isso gera um efeito colateral, pois se adicionarmos um método latir()
na classe cachorro, a classe gato automaticamente estaria o herdando.
Uma alternativa para resolver tal situação, sem ter que duplicar código, seria utilizar a composição. Aqui entra a extração das partes em comum para uma outra classe, e a substituição da herança:
public class DadosDoAnimal {
private String nome;
private LocalDate dataNascimento;
private String raca;
private String cor;
private BigDecimal peso;
}
public class Cachorro {
private DadosDoAnimal dados;
}
public class Gato {
private DadosDoAnimal dados;
}
Esse é um exemplo da composição substituindo a herança e mesmo assim evitando a duplicação de códigos.
Bons estudos!