2012-01-15 13 views
11

Sto lavorando al mio primo vero progetto con Java. Sto iniziando a sentirmi a mio agio con la lingua, anche se ho più esperienza con i linguaggi dinamici.Metaprogramming Java

ho una classe che si comportano simile al seguente:

class Single 
{ 
    public void doActionA() {} 
    public void doActionB() {} 
    public void doActionC() {} 
} 

E poi ho una classe di SingleList che agisce come un insieme di queste classi (in particolare, è per una libreria 2D Sprite, e la " azioni "sono tutti i tipi di trasformazioni: rotazione, taglio, scala, ecc.). Voglio essere in grado di effettuare le seguenti operazioni:

class SingleList 
{ 
    public void doActionA() { 
     for (Single s : _innerList) { 
      s.doActionA(); 
     } 
    } 

    ... etc ... 
} 

Esiste un modo per rinviare semplicemente un metodo (o un elenco noto di metodi) per ciascun membro della lista interna? In qualche modo senza dover elencare in modo specifico ciascun metodo, quindi eseguire il ciclo di ciascun membro interno e applicarlo manualmente?

Per rendere le cose un po 'più difficili, i metodi sono di varia natura, ma sono tutti di tipo restituito "vuoto".

+0

Penso che si può dare un'occhiata a Java riflessione, che consente di chiamare i metodi in fase di esecuzione. – Alvin

+0

Ma avrei comunque bisogno di generare tutti gli stub del metodo nella classe SingleList. Sto cercando una soluzione che funzioni come metodo invocato catch-all. Molto simile al richiamo in PHP o in python getattr. – efritz

+0

oh non è necessario attivarlo, con il riflesso si può fare SingleList.get ("someAttr"), quindi il riflesso chiamerà il metodo getSomeAttr() per te. Puoi Google "org.springframework.beans.BeanUtils", che fa quello che vuoi. Scriverò un esempio come risposta formale più tardi se nessuno mi picchia aha haha. – Alvin

risposta

11

Sfortunatamente Java non supporta facilmente la creazione di classi in fase di esecuzione, che è ciò che è necessario: lo SingleList deve essere aggiornato automaticamente con i metodi di stub necessari per abbinare la classe .

mi vengono in mente i seguenti approcci a questo problema:

  1. Uso Java reflection:

    • Pro:
      • E 'facilmente reperibile in linguaggio Java e si può facilmente trovare documentazione ed esempi.
    • Contro:
      • La classe SingleList non sarebbe compatibile con l'interfaccia Single classe di più.
      • Il compilatore Java e gli IDE in genere non sono in grado di aiutare con i metodi chiamati tramite reflection: gli errori che verrebbero rilevati dal compilatore vengono in genere trasformati in eccezioni di runtime.
      • A seconda dei casi d'uso, è possibile che si verifichi anche un notevole calo delle prestazioni.
  2. Utilizzare un sistema di generazione con una sorta di generatore di codice sorgente per creare automaticamente il file SingleList.java.

    • Pro:
      • Una volta lo si imposta non dovranno fare i conti con essa più.
    • Contro:
      • come impostare questa funzione ha un grado di difficoltà.
      • È necessario assicurarsi separatamente che la classe SingleList caricata in qualsiasi JVM o IDE, in questo caso, corrisponda effettivamente alla classe caricata.
  3. affrontare questo problema manualmente - creare un'interfaccia (ad esempio SingleInterface) o una classe astratta di base per l'uso da entrambe le classi dovrebbe aiutare, poiché qualsiasi IDE discreto indicherà metodi non implementati. Un'architettura di classe adeguata ridurrebbe al minimo il codice duplicato e l'IDE potrebbe essere in grado di aiutare a generare le parti di piastra di prova.

    • Pro:
      • Non c'è alcuna curva di messa a punto per superare.
      • L'IDE vedrà sempre l'insieme giusto di classi.
      • L'architettura di classe viene in genere migliorata in seguito.
    • Contro:
      • Tutto è manuale.
  4. utilizzare una libreria bytecode generazione come Javassist o BCEL per generare dinamicamente/modificare la classe SingleList on-the-fly.

    • Pro:
      • questo metodo è estremamente potente e può risparmiare un sacco di tempo nel lungo periodo.
    • Contro:
      • Uso delle librerie di generazione di bytecode è tipicamente non banale e non per i deboli di cuore.
      • A seconda di come si scrive il codice, è possibile che si verifichino problemi con l'IDE e la gestione delle classi dinamiche.
+0

Sembra che l'approccio manuale sia la strada da percorrere. Dovrò solo assicurarmi di mantenere l'interfaccia aggiornata se aggiungo ulteriori trasformazioni. – efritz