Como implementar apenas parte de uma interface

14

Ao desenvolver no OOP, algumas vezes uma interface / contrato é fornecida por uma biblioteca que você não pode alterar. Vamos chamar essa interface J.

Agora você tem um objeto da classe A que consome objetos que implementam essa interface. Dentro de Apenas uma pequena parte das definições da interface é necessária. Algumas das classes de objetos são criadas por mim durante o projeto (vamos chamar uma delas de tipo D), portanto há uma sobrecarga na implementação de tudo dentro da interface J.

Eu quero implementar um subconjunto da funcionalidade na interface J, mas minhas soluções até agora não me satisfazem:

  • implementar todos os aspectos de J e depois lançar "notImplementedExceptions" desinforma o usuário dos meus objetos: parece que meus objetos do tipo D estão em conformidade com a interface J, mas não - e outros consumidores dos meus objetos (que aceitam objetos que implementam a interface J) não pode confiar na integridade dos meus objetos.
  • A implementação de uma interface recém-definida me proíbe de usar objetos que implementam apenas a interface J, embora a interface J seja totalmente compatível com minha própria interface.
  • Permitir que meus objetos personalizados implementem a interface J criaria uma sobrecarga significativa, porque eles não precisam de toda essa funcionalidade.

Quando eu era capaz de alterar a interface J, eu criava uma "super interface" K que tinha esse subconjunto da funcionalidade da interface J e fazia a interface J herdar da interface K. Mas não posso alterar a interface J.

O que é uma solução orientada a objetos para esse problema? A melhor solução ainda está implementando a interface "justa" J? Ou existem maneiras de "superclasse" de uma interface sem alterá-la?

vstrien
fonte
1
Veja como as classes * Adapter no Swing fazem isso.

Respostas:

9

se você não controla a interface J, está preso.

para maior clareza, você pode implementar sua própria interface subJ e interface J e usar subJ em seu próprio código para deixar claro que os métodos extras na interface J não são necessários, mas não acho que isso realmente lhe valha muito

se possível, implemente toda a interface J completamente

se possível, entre em contato com o proprietário da interface J e peça que ele a altere para melhor atender às suas finalidades

Steven A. Lowe
fonte
2
Como compromisso: você pode pedir ao proprietário da interface J para herdar da sua interface menor SubJ.
K3b
27

O objetivo principal da implementação de uma interface é fornecer um contrato firme entre o chamador e o chamado que nunca muda enquanto os detalhes da implementação podem variar.

Ao implementar a interface J, você está dizendo ao mundo exterior o que pode fazer.

Se você não precisa da metade do que J faz, então a interface deve ser subdividida, pois não é tão pequena quanto poderia ser, ou você precisa usar NotImplementedExceptionos métodos e propriedades que não precisa. No entanto, essa não é a melhor solução, pois confunde as expectativas das pessoas sobre o que seu código pode fazer.

ChrisF
fonte
5

Se sua classe de consumidor A não exigir toda a interface J, sugiro que crie uma nova interface (chame-a K), que descreva de forma abrangente tudo o que exige.

Isso fornece um sinal claro para quem usa a classe A quanto ao lado do contrato. Melhorando assim as chances de reutilização. Se alguém precisar fornecer um objeto que implemente uma interface grande e complexa, para fazer algo relativamente simples, provavelmente terminará escrevendo a classe A que fizer.

Para permitir que a classe A consuma objetos que implementam apenas a interface J, é possível fornecer uma classe de wrapper que implemente a interface K e transmita as chamadas apropriadas para um membro J da interface.

Paul Butcher
fonte
3

Embora eu concorde com as respostas existentes que dizem que você realmente precisa implementar J completamente (com exceções para métodos não implementados) ou não, uma solução possível é a seguinte:

  • Crie uma interface menor K que é um subconjunto de J e implemente os métodos necessários.
  • Crie um wrapper para A que aceite objetos que implementam J e K.
  • No caso de uma passagem em J, simplesmente envie-a para a instância de A.
  • No caso de uma passagem em K, instancie uma implementação anônima de J, conectando apenas os métodos de K a J existentes. Passe o resultado para a instância de A.

Observe que essa é uma solução bastante feia, pois requer um invólucro que aceita várias coisas que são essencialmente a mesma coisa. Mas consegue o seguinte:

  • Nenhuma alteração em J ou A.
  • Nenhuma implementação "exposta" de J que esteja incompleta.

Se o seu idioma OO não permitir instanciação anônima da interface, você poderá criar uma implementação fictícia da interface e instanciar isso.

Deckard
fonte
1

Quanto tempo levaria para implementar a interface inteira?

Se você levar um tempo considerável, isso indica um problema de design, e eu aconselho você (como Steven A. fez antes de mim) a entrar em contato com o proprietário e verificar se isso pode ser alterado no futuro.

Você usa a interface em seu próprio código, independente da biblioteca da interface?

Como sugeriu Steven A., você pode usar sua própria interface como gostaria de vê-la em seu próprio código. Isso mantém pelo menos o seu código interno limpo. Você também pode enviar isso ao proprietário como a interface que você esperaria encontrar. Talvez ele concorde com você, ou talvez ele possa explicar por que a interface não deve ser dividida.

Sua implementação precisaria dos membros não utilizados da interface?

Caso você possa esperar que eles nunca sejam chamados, pois 'não são suportados', eu prefiro usar o NotSupportedException. Isso fornece uma indicação clara de que você nunca suportará essa interface, e não a implementou.

Steven Jeuris
fonte
A boa ideia de usá- NotSupportedExceptionlo deixa claro que você não suporta esse método.
ChrisF
@ ChrisF: eu uso apenas NotImplementedExceptionpara código de produção, onde, de outra forma, escreveria "TODO: Implement this this" Infelizmente, eles não aparecem na lista de tarefas do Visual Studio . Mas, na prática, dificilmente deixo um método não implementado por mais de dois dias. O compartilhador também mostra essas exceções em negrito (pelo menos na minha configuração). :)
Steven Jeuris
0

Implemente o que você precisa e gere uma exceção NoImplementedException nos outros.

Esta é uma questão de uso. Se você não usa a interface ou sabe que seu código não usará a interface, não invista tempo nisso, pois não precisará investir tempo em código redundante.

Trabalhe para a tarefa em mãos e mantenha uma boa trilha para que outras pessoas sigam se quiserem usar a interface.

Muitas interfaces em Java não são implementadas ao máximo.

Esta é a abordagem do Apache para as coisas: http://commons.apache.org/lang/api-2.4/org/apache/commons/lang/NotImplementedException.html

Nome em Exibição
fonte
Talvez discuta por que você acredita que esta é uma solução adequada. Isso não acrescenta nada à pergunta.
Steven Jeuris
não há necessidade de implementar tudo, pois não há necessidade real de explicar tudo. se fosse esse o caso, partes da interface eram redundantes, ele a pegaria imediatamente.
Exibir nome