2012-12-21 15 views
18

Supponiamo che io ho seguito struttura di classe:metodo generico che accettano solo una parte delle classi

class Base {} 
class A extends Base {} 
class B extends Base {} 
class C extends Base {} 

Voglio scrivere il metodo, che accetta le istanze di A e B ma non istanze di C.
Posso ottenerlo in Java?

So che questo non è una buona situazione di successione (A e B dovrebbe avere genitore comune diverso da C), ma sono solo curioso è in modo Java per gestire situazione come questa.

MODIFICA:
!!!
So che una migliore ereditarietà risolverà il problema. Sono solo curioso, se Java ha qualche meccanismo standard per risolvere un problema del genere.
!!!

risposta

3

credo che la risposta alle vostre domande è "No, Java non ha un modo standard di trattare con un tale problema". E se hai questo problema, puoi guardare altre risposte qui, come riparare l'ereditarietà o usare la tecnica intelligente given by MrSmith42.

+0

Grazie per la risposta corretta e semplice :) –

+4

@ MichałHerman è corretto? 17 - 1 ... blimey, è come essere al lavoro. – NimChimpsky

+0

@NimChimpsky non ti preoccupare, ci sono i badge per questo genere di cose. :) – MikeTheLiar

2

È possibile utilizzare instanceof per verificare se un oggetto è di un determinato tipo.

Una migliore idea sarebbe una migliore struttura di ereditarietà, ovviamente.

+0

Per essere chiari: in Java, 'instanceof' funziona per sottoclassi. Cioè, 'C c = new C(); c instanceof B' restituirà true. Se si desidera escludere 'C', è necessario verificarlo esplicitamente. (Aggiungendo un commento perché a prima vista questa risposta non mi è stata chiara.) –

13

È possibile utilizzare un'interfaccia? per esempio.

class Base {} 
interface MyGenericInterface {} 
class A extends Base implements MyGenericInterface {} 
class B extends Base implements MyGenericInterface {} 
class C extends Base {} 

In questo modo, il metodo può accettare implementazioni di MyGenericInterface, e dal momento che A e B implementare l'interfaccia, ma C non lo fa, la volontà di accettare le istanze di A e B, ma non C, come richiesto.

8

Se qualcosa dovesse accettare A, B ma non C allora si dovrebbe riconsiderare il motivo per cui C eredita dalla Base in primo luogo. Si potrebbe aggiungere un ulteriore livello di eredità:

---Base--- 
    |  | 
--Sub--  C 
|  | 
A  B 

allora si potrebbe permettere il metodo di accettare solo oggetti di tipo Sub. Sub non ha nemmeno bisogno di fare nulla, e sono tutti, tecnicamente, anche Base.

una soluzione più rapida sarebbe una sporca if(arg.instanceof(C)) però ...

8

si può gestire in fase di esecuzione utilizzando eccezione:

void genericMethod(Base arg_in) 
{ 
    if(arg_in instanceof C) 
    { 
     throw IllegalArgumentException("C class not accepted."); 
    } 

    ... 
    ... 
} 
8

Un tipo-gerarchia non deve essere cambiato solo perché si vuole avere un tale metodo Ma il caso in cui si desidera avere un tale metodo potrebbe indicare che si dovrebbe riflettere sulla propria gerarchia di tipi .

Ma se si è sicuri i vostri tipi sono ben progettati, che dire di questo approccio:

public class T { 

     public void doSomething(final A a) { 
      doSomthing(a); 
     } 

     public void doSomething(final B b) { 
      doSomthing(b); 
     } 

     private void doSomthing(final Base b) { 

      // Here is the implementation 

     } 

    } 
+0

Non so cosa avessi intenzione di utilizzare con la parola chiave 'final', ma non impedirò che si verificasse una conversione allargata alla chiamata luogo. Poiché ogni istanza di 'C' è un'istanza di' B', sarà sempre possibile passare istanze di 'C' nel metodo' doSomething() '. –

+0

Perché pensi che "C sia un'istanza di B"? A, B, C estendono solo la base – MrSmith42

+0

"final" non ha nulla a che fare con la funzionalità. Solo una convenzione di codifica a cui sono abituato. – MrSmith42

2

Generics è per tipo di sicurezza. Periodo. Non "permettere" o "non consentire" cose arbitrarie. Non esiste alcun motivo di sicurezza del tipo per consentire A e B e non C.

Problemi correlati