Portanto, sou bastante novo em programação no mundo real (fora dos projetos acadêmicos) e encontrei muitas postagens dizendo que usar instanceof
é uma coisa ruim para determinar a classe de um objeto específico.
Minha situação é que eu tenho três classes, uma classe de produto base, uma que se estende a isso e outra que se estende a isso. Todos eles são armazenados na mesma tabela em um banco de dados e eu tenho algum código que precisa usar os métodos em cada um para extrair dados deles.
Qual é a melhor prática para contornar essa maneira de fazê-lo? Eu li algumas coisas sobre polimorfismo, mas não consigo encontrar exemplos que resolvam o problema que tenho. Todos eles geralmente substituem um método que, para mim, não funciona, pois preciso extrair coisas diferentes dos diferentes objetos.
Existe uma maneira melhor de fazer isso ou estou preso a usar instanceof
ou algum tipo de reflexão para obter os campos específicos dos objetos?
fonte
instanceof
- chave esteja errada; tentar encontrar a classe de um objeto geralmente é o problema. Nem sempre está errado, mas provavelmente no seu caso está. Talvez se você nos contar o que está tentando realizar, podemos sugerir uma solução usando o polimorfismo.getSpecifics()
que é implementado de maneira diferente em cada um, com cada um retornando os dados específicos da classe?Respostas:
O motivo
instanceof
é desencorajado é que não é OOP.Não deve haver razão para o chamador / usuário de um objeto saber em qual classe concreta é uma instância e além de qual tipo a variável é declarada.
Se você precisar de um comportamento diferente nas subclasses, adicione um método e implemente-o de maneira diferente.
fonte
getSpecifics()
(ou algo semelhante) em cada classe que retornará os detalhes para cada classe. Essa é a melhor abordagem?List
. Eu passo para um objeto que aceita qualquerIterable
. Agora, esse segundo objeto passa-o para um terceiro objeto que usa umList
para otimização ou um,Iterable
mas é muito mais lento. O segundo não deveria saber que é uma lista, mas o terceiro gostaria muito de saber. O terceiro objeto não deve verificar, por exemplo, se é possível aplicar a otimização? Veja, por exemplo, goiabaFluentIterable
que faz exatamente isso.instanceof
.instanceof
não é necessariamente uma coisa ruim, no entanto, é algo que se deve olhar.Um exemplo de onde funciona corretamente está em um local em que se obtém uma coleção do tipo base e você deseja apenas os de um subtipo. Obter os endereços de rede
NetworkInterface.getNetworkInterfaces()
retorna objetos NetworkInterface que possuem uma coleção de objetos InetAddress, alguns dos quais são Inet4Address e outros são Inet6Address. Se alguém quiser filtrar a coleção de objetos Inet4Address, é necessário usar instanceof.Na situação que está sendo descrita na postagem original, há uma classe Base, algo que estende essa classe base e algo que estende a classe estendida. Embora não seja totalmente informativo, isso parece ter os fundamentos de um design menos que o ideal.
Quando você está retornando uma classe base, a menos que haja uma boa razão para ela ser projetada dessa maneira (compatibilidade com versões anteriores entre as especificações de uma versão anterior), você não deve tentar espiar os tipos subjacentes. Se você devolver um conjunto, sabe que está recebendo um conjunto. Isso permite que o desenvolvedor mude de ideia posteriormente para retornar um tipo mais específico (SortedSet) ou altere o tipo subjacente (HashSet para TreeSet) sem interromper nada.
Reconsidere seu design de como os objetos são estruturados e parentais para ver se é possível criar um modelo de classe melhor que não exija uma distinção de tipos.
fonte
isOfType(SomeEnum.IPv4)
método poderia ser uma maneira melhor de filtrar essas qualidades do que inspecionar o tipo de concreto viainstanceof
. E se você quiser dividir sua classe de implementação IPv4 posteriormente? Não que isso seja sempre melhor, mas é uma consideração.(o instanceof Serializable) || (o instanceof Externalizable)
. instanceof é melhor que a alternativaVocê pode usar o método getClass ().
Tem certeza de que precisa de três classes diferentes? Talvez uma classe com um interruptor dentro sirva melhor?
fonte
getClass
einstanceof
compartilhar desvantagens. O polimorfismo é melhor do que ambos quando se encaixa, e não vejo que não se encaixe no caso de uso do OP.getClass
posso não ainda compartilham o mesmo problema que usarinstanceof
? Ainda terei que descobrir qual deles tenho e depois chamar um conjunto de funções. Idealmente, quero um método que retorne os dados específicos para essa classe sem precisar converter para esse objeto.getClass
é a melhor maneira de fazê-lo, não tem negócio tendo a maior parte uma resposta ;-)Normalmente, quando me vejo querendo saber o tipo de algo, isso significa que implementei minha estrutura de objetos incorretamente. Na maioria das vezes, isso se resume a violar o LSP .
No entanto, há momentos em que eu gostaria de ter uma maneira de enviar dinamicamente e economizar uma tonelada de código de chapa de caldeira e proteger minha estrutura de objetos à prova de futuro. O C # fornece a palavra-chave dinâmica nas parcelas mais recentes da estrutura, mas até onde eu sei, o Java ainda não possui algo parecido.
Dito isso, instanceof é geralmente melhor do que comparar classes, pois suportará a herança corretamente. Você também pode usar métodos como isAssignableFrom e outros da API de reflexão. Se você deseja implementar algo como despacho dinâmico, isso pode ser feito através da API de reflexão, mas cuidado, será lento. Use com cuidado; idealmente, você deve corrigir a estrutura do objeto e a criação do seu aplicativo, se puder.
Espero que isto ajude
fonte