AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 78379697
Accepted
zeldinho
zeldinho
Asked: 2024-04-24 23:44:00 +0800 CST2024-04-24 23:44:00 +0800 CST 2024-04-24 23:44:00 +0800 CST

Composição sobre herança - duplicação de código

  • 772

Gostaria de receber alguns esclarecimentos sobre como implementar adequadamente a 'Composição sobre Herança'. Acho que tenho uma noção da teoria, mas na prática tenho dificuldade em entender como isso não leva à duplicação de código.

Tenho o seguinte exemplo (é Java): suponha que temos uma classe animal abstrata:

abstract class Animal {
    protected void eat() {
        // Common eating implementation
    }

    protected void sleep() {
        // Common sleeping implementation
    }
}

E queremos construir animais voadores e nadadores. Entendo que a melhor maneira de fazer isso para seguirmos o LSP é com interfaces para cada um:

interface Flyer {
    void fly();
}

interface Swimmer {
    void swim();
}

Então teríamos

class Salmon extends Animal implements Swimmer {
    @Override
    public void swim() {
        // Swim implementation
    }
}

class Sparrow extends Animal implements Flyer {
    @Override
    public void fly() {
        // Fly implementation
    }
}

Mas então temos um novo requisito para Magpieque voe da mesma forma que um pardal. Criaríamos a classe, não muito diferente de Sparrow:

class Magpie extends Animal implements Flyer {
    @Override
    public void fly() {
        // Same exact fly implementation as Sparrow.fly
    }
}

Imagine, para o propósito deste exercício, que a implementação fly é muito complexa com integração de banco de dados, registro, etc. - isso leva a uma carga de código duplicado e se adicionarmos mais pássaros ou peixes, precisaremos duplicar o código ainda avançar.

Houve também a ideia de ter uma classe abstrata para o mesmo tipo de panfletos como

abstract class FlyingBird extends Animal implements Flyer

e temos a implementação comum lá, mas e se precisarmos criar alguns deles e houver um animal que precise estender dois deles? É uma ladeira escorregadia...

Existe alguma maneira de evitar isso? Ou estou errando o alvo em algum lugar?

oop
  • 1 1 respostas
  • 17 Views

1 respostas

  • Voted
  1. Best Answer
    ash
    2024-04-24T23:56:08+08:002024-04-24T23:56:08+08:00

    Na composição, que sou a favor da herança para compartilhar código por vários motivos, você pode tentar compartilhar código injetando uma implementação comum.

    No seu exemplo, você poderia ter um impl Flyer que pode ser compartilhado entre Sparrow e Magpie. Nomeá-lo pode ser um pouco difícil - recomendo usar o princípio "usar antes de reutilizar" e, portanto, apenas dê um nome bom o suficiente e refatore mais tarde, se necessário.

    Então, por exemplo, você poderia ter uma implementação SmallBirdFlyer, injetá-la nas implementações Sparrow e Magpie e, em seguida, usar a delegação de Sparrow e Magpie para esse impl. Ou, em vez de fazer com que Sparrow e Magpie implementem Flyer diretamente, você pode fazer com que eles retornem um Flyer por meio de um método, como getFlyer(), e então Sparrow e Magpie poderiam retornar diretamente o impl SmallBirdFlyer lá.

    Aqui está um exemplo usando delegação:

    class Magpie implements Animal, Flyer {
        private SmallBirdFlyer myFlyer;
    
        public void setMyFlyer(SmallBirdFlyer myFlyer) {
            this.myFlyer = myFlyer;
        }
    
        @Override
        public void fly() {
            this.myFlyer.fly();
        }
    }
    

    Eu penso desta maneira - em vez de reduzir a funcionalidade do nível superior e depois encontrar maneiras de personalizar nos níveis inferiores, crie a funcionalidade comum para uso no nível superior.

    • 3

relate perguntas

  • É necessário retornar o mesmo objeto em métodos com interface fluente

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle?

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Quando devo usar um std::inplace_vector em vez de um std::vector?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Martin Hope
    Aleksandr Dubinsky Por que a correspondência de padrões com o switch no InetAddress falha com 'não cobre todos os valores de entrada possíveis'? 2024-12-23 06:56:21 +0800 CST
  • Martin Hope
    Phillip Borge Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle? 2024-12-12 20:46:46 +0800 CST
  • Martin Hope
    Oodini Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores? 2024-12-12 06:27:11 +0800 CST
  • Martin Hope
    sleeptightAnsiC `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso? 2024-11-09 07:18:53 +0800 CST
  • Martin Hope
    The Mad Gamer Quando devo usar um std::inplace_vector em vez de um std::vector? 2024-10-29 23:01:00 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST
  • Martin Hope
    MarkB Por que o GCC gera código que executa condicionalmente uma implementação SIMD? 2024-02-17 06:17:14 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve