2013-02-02 18 views
15

In Java, è possibile definire un'interfaccia con un metodo che riceve un argomento della classe di implementazione?Java Generics: metodo di interfaccia che riceve l'argomento di tipo della classe di implementazione

interfaccia:

public interface MyInterface { 
    public <T is/extends of the type of the implementing class> void method(T object); 
} 

classe:

public class A implements MyInterface { 

    public void method(A object) { 
     ... 
    } 

} 

Quello che voglio evitare è che una classe potrebbe implementare MyInterface con un'altra classe come se stesso.

Quindi questo non dovrebbe essere consentito:

public class A implements MyInterface<B> { 

    public void method(B object) { 
     ... 
    } 

}  





Edit:

Ok provo a descrivere in altro modo ciò che voglio raggiungere . Voglio avere diverse classi che hanno un metodo che accetta un argomento di quel tipo di classe. Quindi, in aggiunta alla classe A dall'alto Diciamo C'è un'altra classe B che assomiglia a questo:

public class B implements MyInterface { 

    public void method(B object) { 
     ... 
    } 

} 

quello stand classi A e B hanno in comune è un metodo chiamato "metodo" che riceve un ARG del tipo di classe stessa.

Nel mio progetto voglio raggiungere il seguente. Sto scrivendo un piccolo gioco e voglio implementare una sorta di rilevamento delle collisioni. fondamentalmente voglio farlo facendo alcune chiamate polimorfiche "intelligenti".

ho definito un ICollisionReceiver un'interfaccia che assomiglia a questo:

public interface ICollisionReceiver<T extends IShape> extends IShape { 

    public boolean collides(T t); 

} 

e ho definito un'altra interfaccia come questa:

public interface ICollisionChecker<T extends ICollisionChecker<T>> extends IShape { 

    public void addCollisionReceiver(ICollisionReceiver<T> receiver); 

    public void removeCollisionReceiver(ICollisionReceiver<T> receiver); 

} 

Ora, per esempio, il mio lettore implementa l'interfaccia ICollisionReceiver come il giocatore riceve collisioni e li gestisce. Questo dovrebbe essere fatto in modo generico, così per esempio ho scatole e cerchio, ora il giocatore implementa ICollisionReceiver < Box> e ICollisionReceiver < Circle> così ho entrambi i metodi

@Override 
public boolean collides(final Box b) {   
    ... 
    return false; 
} 

e

@Override 
public boolean collides(final Circle c) {   
    ... 
    return false; 
} 

nella mia casella e la classe cerchio posso registrare ICollisionReceivers e poi faccio la seguente nel metodo di aggiornamento:

boolean conti = true; 
    int i=0; 
    while(conti && i<collisionReceivers.size()) { 
     final ICollisionReceiver<Bonus> rec = collisionReceivers.get(i);    
     if(this.collidesWith(rec)) { 
      conti = rec.collides(this); 
     }    
     ++i; 
    } 

controlla sostanzialmente se questa scatola si scontra con un determinato ricevitore e quindi chiama il metodo collides() dei ricevitori.

Ora il punto è, voglio assicurarmi che entrambe le classi box e circle implementino l'interfaccia ICollisionChecker solo con il loro tipo.

ho esplicitamente possibile farlo facendo qualcosa di simile

public class Bonus extends AnimatedSprite implements ICollisionChecker<Bonus>... 

ma questo non è molto soddisfacente per me ...

Ci scusiamo per il lungo post, spero che questo rende evidente.

+2

'public metodo void (oggetto T);' non è un'opzione? poiché se sono onesto non ho capito cosa vuoi ottenere. – Zhedar

risposta

20

ciò che si vuole non è possibile in Java, e non è utile.

Quindi questo non dovrebbe essere consentito:

Perché no? Che scopo serve? Generics non fa per te restrizioni arbitrarie. Generics è utile solo per eliminare i cast che altrimenti avresti bisogno, perché può dimostrare che il cast è sempre sicuro.

Finché public class A implements MyInterface<B> è protetto dal tipo, non vi è alcun motivo nel fare una restrizione arbitraria che lo proibisca.

Si dovrebbe definire semplicemente l'interfaccia come

public interface MyInterface<T> { 
    public void method(T object); 
} 

e si può definire la classe

public class A implements MyInterface<A> { 
    public void method(A object) { 
    } 
} 

e se qualcun altro definisce una classe

public class B implements MyInterface<A> { 
    public void method(A object) { 
    } 
} 

allora così sia. Perché ti interessi? Che problema provoca?

+2

Ha, sapevo che eri tu dopo la prima frase. Sempre cercando di eseguire il CRTP fuori città :) –

+1

sì, è una restrizione che potrebbe non essere l'intento dei generici in generale, ma fornisce anche un qualche tipo di sicurezza del tipo in quanto si sarebbe assicurato che un tipo gestisse solo le collisioni di questo tipo stesso. Quindi ho pensato/sperato che fosse possibile. tuttavia, grazie mille per la tua risposta. – zersaegen

-1

Che cosa si vuole fare è probabilmente qualcosa di simile:

public interface MyInterface <T extends A> { 
    public void method(T object) { 
     ... 
    } 
} 

public class A implements MyInterface<A_or_class_extending_A> 
{ ... } 

Spero che questo ha aiutato!

+0

È inoltre necessario specificare la dichiarazione dell'interfaccia come 'interfaccia pubblica MyInterface ' per Java per sapere cosa 'T' è. – Michael

+1

grazie per la tua risposta. sfortunatamente questo permette ancora a ClassImplementingMyInterface di essere una classe che non è A. – zersaegen

+0

In realtà questo non è necessario - Ho dichiarato il generico per il metodo, non per la classe! – Pethor

4

Bene, questo è almeno possibile:

public interface SelfImplementer<T extends SelfImplementer<T>> { 
    void method(T self); 
} 

Come si può vedere, la dichiarazione generica sembra un po 'come ricorsione infinita e sono abbastanza sicuro che se Java non ha hanno la cancellazione di tipo , sarebbe - per fortuna tutti i generici sono in realtà Objects dopo compilatore ha affrontato con loro in modo da poter fare questo

public class Impl implements SelfImplementer<Impl> { 
    @Override 
    public void method(Impl self) { 
     System.out.println("Hello!"); 
    } 
} 

e come previsto, questo

(?)
public static void main(String[] args) { 
    Impl impl = new Impl(); 
    impl.method(impl); 
} 

stampe fuori

Hello! 
+2

Come nota a piè di pagina, trovo che questo sia completamente privo di senso e non incoraggerei nessuno a usarlo effettivamente. – Esko

+0

grazie ma sarei ancora in grado di farlo: ImplBlubb di classe pubblica implementa SelfImplementer , quindi ImplBlubb implementerebbe l'interfaccia con Impl. Quello che voglio è che è solo possibile che ImplBlubb implementa l'interfaccia con ImplBlubb e che Impl può implementare l'interfaccia solo con Impl ... – zersaegen

+0

Questo non fa ciò che l'OP vuole. Puoi ancora avere 'publicOne SomeOtherImpl implementa SelfImplementer ' – newacct

Problemi correlati