Herança e composição são dois conceitos fundamentais na programação orientada a objetos (OOP), mas são usados de maneira diferente e têm propósitos diferentes. O objetivo desta postagem é revisar esses propósitos e algumas coisas que você deve ter em mente ao escolhê-los.
Quando pensamos em aplicar herança em nossos projetos, temos que entender:
Por outro lado, se pensarmos em compor objetos juntos:
A questão de saber se a composição é melhor que a herança ou vice-versa é um tópico debatido no design de software. Ambas as abordagens têm as suas vantagens e desvantagens, e a escolha depende do contexto e dos requisitos específicos do projeto. Aqui apresentarei um exemplo onde a composição pode ser preferível à herança.
Vamos explorar um exemplo em Java que ilustra como a composição pode ser preferível à herança em certos casos. Suponha que estejamos trabalhando em um sistema de processamento de pedidos em uma loja online.
Primeiro, vamos considerar uma abordagem que usa herança para representar diferentes tipos de produtos compráveis, como livros e eletrônicos:
// Clase base para productos class Producto { String nombre; double precio; Producto(String nombre, double precio) { this.nombre = nombre; this.precio = precio; } void procesarPedido() { System.out.println("Procesando pedido para " nombre); } } // Clase para productos electrónicos que hereda de Producto class ProductoElectronico extends Producto { String modelo; ProductoElectronico(String nombre, double precio, String modelo) { super(nombre, precio); this.modelo = modelo; } } // Clase para libros que hereda de Producto class Libro extends Producto { String autor; Libro(String nombre, double precio, String autor) { super(nombre, precio); this.autor = autor; } }
Essa abordagem funciona, mas e se você precisar introduzir novos tipos de produtos ou adicionar funcionalidades específicas para determinados tipos de produtos?
Em vez de confiar inteiramente na herança, poderíamos usar a composição para lidar com diferentes tipos de produtos de forma mais flexível:
// Clase para productos class Producto { String nombre; double precio; Producto(String nombre, double precio) { this.nombre = nombre; this.precio = precio; } void procesarPedido() { System.out.println("Procesando pedido para " nombre); } } // Clase para productos electrónicos que utiliza composición class ProductoElectronico { Producto producto; String modelo; ProductoElectronico(String nombre, double precio, String modelo) { this.producto = new Producto(nombre, precio); this.modelo = modelo; } // Puedes agregar lógica específica para productos electrónicos si es necesario void procesarPedidoEspecifico() { System.out.println("Procesando pedido específico para " producto.nombre); } } // Clase para libros que utiliza composición class Libro { Producto producto; String autor; Libro(String nombre, double precio, String autor) { this.producto = new Producto(nombre, precio); this.autor = autor; } // Puedes agregar lógica específica para libros si es necesario void procesarPedidoEspecifico() { System.out.println("Procesando pedido específico para " producto.nombre); } }
Nesta abordagem, cada tipo de produto possui uma instância da classe Produto, permitindo que uma lógica comum seja compartilhada para o processamento de pedidos. Além disso, cada tipo de produto pode ter sua própria lógica específica usando métodos como processSpecificOrder(). Esse design é mais flexível e facilita a introdução de novos tipos de produtos ou a modificação da lógica específica do tipo sem afetar a hierarquia de herança.
Embora a escolha entre herança e composição no design de software dependa do contexto e dos requisitos específicos do problema que você está abordando. Aqui estão algumas situações em que você pode considerar a herança como uma opção mais apropriada do que a composição:
class Vehiculo { // ... } class Automovil extends Vehiculo { // ... }
class Animal { void comer() { // Lógica común para comer } } class Perro extends Animal { void ladrar() { // Lógica específica para ladrar } }
class Figura { void dibujar() { // Lógica común para dibujar una figura } } class Circulo extends Figura { void dibujar() { // Lógica específica para dibujar un círculo } } class Cuadrado extends Figura { void dibujar() { // Lógica específica para dibujar un cuadrado } }
Se continuarmos a avaliar os prós e os contras da herança, um dos problemas que podem surgir de uma má herança é que violaríamos o Princípio de Segregação de Interface, que afirma que os clientes não devem ser forçados a depender das interfaces que eles fazem não use. Se uma interface for estendida de uma forma que inclua métodos que não são relevantes para todas as implementações, os clientes que usam essa interface poderão ser forçados a implementar ou depender de métodos de que não precisam, o que pode levar a um design menos limpo e mais difícil. manter.
Em resumo, a herança se concentra no relacionamento "é um" e é usada para modelar hierarquias de classes, enquanto a composição se concentra no relacionamento "tem um" e é usada para construir objetos complexos a partir de outros objetos mais simples. Ambas as abordagens têm seus casos de uso específicos e são escolhidas com base na estrutura e na natureza dos relacionamentos no design do software.
Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.
Copyright© 2022 湘ICP备2022001581号-3