"Se um trabalhador quiser fazer bem o seu trabalho, ele deve primeiro afiar suas ferramentas." - Confúcio, "Os Analectos de Confúcio. Lu Linggong"
Primeira página > Programação > Composição vs Herança

Composição vs Herança

Publicado em 2024-11-09
Navegar:242

Composición vs Herencia

Introdução

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.

Conceitos de herança

Quando pensamos em aplicar herança em nossos projetos, temos que entender:

  • Definição: Na herança, uma classe (chamada de classe derivada ou subclasse) pode herdar propriedades e comportamentos de outra classe (chamada de classe base ou superclasse). A classe derivada pode estender ou modificar a funcionalidade da classe base.
  • Relacionamento: É um relacionamento “é um” (é-um). Por exemplo, se você tem uma classe “Veículo” e outra classe “Carro”, a classe “Carro” é uma subclasse de “Veículo”.
  • Vantagens: Promove a reutilização de código e permite fácil extensão da funcionalidade.

Conceitos de composição

Por outro lado, se pensarmos em compor objetos juntos:

  • Definição: Na composição, um objeto contém outros objetos e delega parte de sua funcionalidade a eles. Em vez de herança, uma classe usa instâncias de outras classes para alcançar sua funcionalidade.
  • Relacionamento: É um relacionamento do tipo "tem um". Por exemplo, se você tem uma classe "Motor" e uma classe "Carro", a classe "Carro" pode ter um objeto da classe "Motor".
  • Vantagens: Maior flexibilidade e menor acoplamento entre classes. Mudanças em uma classe não afetam diretamente a outra.

Por que composição sobre herança?

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.

  • Abordagem de herança:

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?

  • Foco com composição:

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.

Quando aplicar 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:

  • Relacionamento "é um": A herança é especialmente apropriada quando há um relacionamento "é um" claro entre as classes. Se uma classe B for uma versão mais específica ou especializada de uma classe A, então a herança faz sentido. Por exemplo, se você tiver uma classe Veículo e uma classe Carro, o relacionamento “é um” é claro, pois um carro é um tipo de veículo.
class Vehiculo {
    // ...
}

class Automovil extends Vehiculo {
    // ...
}
  • Reutilização de código: A herança permite a reutilização de código, uma vez que a classe derivada herda os membros e métodos da classe base. Isto pode ser benéfico quando há uma quantidade significativa de código comum entre classes relacionadas.
class Animal {
    void comer() {
        // Lógica común para comer
    }
}

class Perro extends Animal {
    void ladrar() {
        // Lógica específica para ladrar
    }
}
  • Polimorfismo: A herança é fundamental para a implementação do polimorfismo, o que permite que classes derivadas forneçam implementações específicas de métodos herdados da classe base. Isso é útil em cenários onde você precisa tratar objetos de classes derivadas de maneira uniforme.
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
    }
}

  • Extensões de funcionalidade: Se você estiver estendendo ou especializando uma funcionalidade existente, a herança pode ser mais natural. Por exemplo, se você estiver desenvolvendo uma biblioteca e fornecer uma classe base com funcionalidade básica, os usuários de sua biblioteca poderão derivar dessa classe base para estender essa funcionalidade.

O que acontece se fizermos uma herança ruim?

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.

Conclusão

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.

Declaração de lançamento Este artigo está reproduzido em: https://dev.to/rlgino/composicion-vs-herencia-4664?1 Se houver alguma violação, entre em contato com [email protected] para excluí-lo
Tutorial mais recente Mais>

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