2010-11-18 23 views
-1

Laissez le code suivant:Comment appeler une méthode en fonction de son type générique?

public abstract class MySuperClass { 
     public abstract void update(); 
     /* ... */ 
    } 

    public class A extends MySuperClass { 
     @Override 
     public void update() { /* ... */ } 
     /* ... */ 
    } 

    public class B extends MySuperClass { 
     @Override 
     public void update() { /* ... */ } 
     /* ... */ 
    } 

    public class Ticket<T extends MySuperClass> { 
     private Class<T> c; 
     public Ticket(Class<T> c){ this.c = c; } 
     public Class<T> getClass() { return this.c; } 
     public void update() { /* HOW TO DO! */ } 
     /* ... */ 
    } 

    public class Main { 
     public static void main(String[] args) { 
     Ticket<A> myTicket1 = new Ticket<A>(A.class); 
     Ticket<B> myTicket2 = new Ticket<B>(B.class); 
     myTicket1.update(); 
     myTicket2.update(); 
     } 
    } 

Comment puis-je mettre à niveau les billets en fonction de son genre (A, B), ou ainsi de suite? Update() est une méthode d'instance, vous aurez donc besoin d'une instance pour l'appeler.

+1

Vous n'avez plus aimé l'analogie métal/bois/voiture? ;) – aioobe

+0

Non, c'est un peu la différence – barroco

+0

J'ai regardé l'autre question qui a été référencée et aioobe a raison. Dans les deux cas, il semble qu'il vous manque certains des concepts d'héritage. Pour faire une mise à jour, tout ce dont j'ai besoin est d'avoir accès à un objet 'MySuperClass'. Peu importe qu'il s'agisse d'un 'A' ou d'un' B', Java sera l'implémentation de 'update()' à utiliser. – unholysampler

Répondre

4

Pourquoi Ticket sait quoi que ce soit à propos de ce que signifie réellement la mise à jour. Il suffit de transférer l'appel à une instance de MySuperClass. Le but des classes génériques est que la classe générique fonctionne avec n'importe quel objet (ou sous-ensemble d'objets) sans avoir besoin de savoir exactement de quel type il s'agit.

public class Ticket<T extends MySuperClass> { 
    private T thing; 
    public Ticket(T thing) { 
    this.thing = thing; 
    } 
    public void update() { 
    thing.update(); 
    } 
    /* ... */ 
} 
0

Ceci peut être réalisé avec

getClass().newInstance().update(); 

En raison de polymorhism, il appellera la méthode correcte de A ou B. Mais pour le résoudre d'une manière plus orientée objet, vous devez passer une instance au constructeur de billets et juste appel mise à jour().

0

J'ai modifié votre exemple pour le rendre plus logique ... et implémenté update.

public class Ticket<T extends MySuperClass> { 
    private Class<T> c; 
    private T t; 

    public Ticket(Class<T> c) throws InstantiationException, IllegalAccessException { 
     this.c = c; 
     this.t = c.newInstance(); 
    } 

    public Class<T> getClass() { 
     return this.c; 
    } 

    public void update() { 
     t.update(); 
    } 
    /* ... */ 
} 

La méthode appelle updatet.update(), transmettra polymorphically à la méthode update de l'objet réel qui fait référence à t. Notez que j'ai ajouté du code pour créer et stocker l'instance de Class<T>.

MISE À JOUR - J'ai ajouté les exceptions au constructeur Ticket. C'est la partie du prix que vous payez pour utiliser la réflexion pour créer des instances ... plutôt que de les créer en utilisant new et en leur passant comme arguments.

+0

Puis-je utiliser la réflexion? – barroco

+0

Vous pouvez. En fait, mon tweak à votre exemple fait; voir 'c.newInstance()'. Mais il n'est pas nécessaire d'utiliser la réflexion pour appeler 't.update()'. –