C'è un problema interno per cui le classi java anonymous non possono implementare e sottoclasse allo stesso tempo? O è solo perché la sintassi?Perché una classe anonima non può implementare più interfacce direttamente? Semplicemente a causa della sintassi o c'è un'altra ragione?
risposta
solo sintassi, le cosiddette classi anonime sono classi normali al 100%. è possibile ottenere risultati funky usando java.lang.reflect.Proxy e InvocationHandler, sarebbe il modo più sporco per farlo.
modi più semplici includono dichiarando la classe nel metodo e solo l'aggiunta di 'strumenti',
classianonimi sono forniti come un modo per costruire in modo rapido e conciso una classe "una tantum". La tua domanda suggerisce che stai tentando di usare la tua anon class in diversi modi (almeno un'interfaccia e una estesa). In questo caso, sarebbe più leggibile e più mantenibile se si promuove quella classe anon a una classe completa.
Ciò eviterebbe anche effetti collaterali inaspettati, gestendo meglio l'incapsulamento delle classi.
Trovato un hack intorno a questo
creare un'interfaccia nella parte inferiore della vostra strega del file si estende tutte le interfacce che si desidera implementa quindi creare una classe anonima, di cui implementa questa.
C'è un problema interno per cui le classi java anonymous non possono implementare e sottoclasse contemporaneamente?
Credo che sia il 99% a causa di motivi sintattici. I parametri di tipo supportano anche intersection types (<T extends InterfaceX & InterfaceY>
), quindi non penso che nel sistema di tipi si verifichino "contraddizioni" o addirittura complicazioni se il supporto per tale funzione verrà aggiunto.
Un'espressione come new (InterfaceX & InterfaceY)() { ... }
potrebbe benissimo essere compilato in qualcosa di simile
interface InterfaceXandY extends InterfaceX, InterfaceY {}
... new InterfaceXandY() { ... }
Il motivo non v'è alcun supporto per esso è probabilmente dovuto al fatto che si tratta di un caso d'uso molto raro, che c'è una soluzione semplice.
Su una nota alquanto correlata. È possibile lasciare un lambda implementare per esempio Serializable
facendo
Runnable r = (Runnable & Serializable)() -> System.out.println("Serializable!");
Vedere How to serialize a lambda?
Ottima risposta +1. Assolutamente d 'accordo sul fatto che se esiste un banale work-around presente, perché fare un cambiamento fondamentale nella lingua e introdurre una sintassi macchinosa di due tipi statici. –
chiusure sono stati lasciati fuori di Java inizialmente più a causa del tempo pressioni di qualsiasi altra cosa . Nei primi giorni di Java la mancanza delle chiusure era piuttosto dolorosa, e così nacquero classi interne: un compromesso scomodo che tentava di evitare un numero di problemi rigidi . Ma come è normale in così tanti problemi di progettazione, le semplificazioni non risolvono veramente alcun problema, semplicemente le spostano.
interessante, ora che le espressioni lambda e chiusure vengono aggiunti a Java, e questa volta strumentato con qualcosa di diverso rispetto a classi interne, potremmo definire un oggetto al volo composto da più di un'interfaccia, a condizione che il secondo uno è l'interfaccia marker.
interface Bar {
default String getName() { return "Bar"; }
}
Object o = (Comparable<Integer> & Bar) (x,y) -> x > y ? x : y;
Bar b = (Bar) o;
System.out.println(b.getName()); //Bar
Questo compila e funziona perfettamente nel mio ultimo build del JDK 8 (12 marzo 2013). Quindi, sembrerebbe che stiano riflettendo maggiormente su questo problema.
Non so che chiamerei questo un hack – Michael