2015-11-17 6 views
9

Dato il seguente disposizione delle classi:Perché la chiamata super in Groovy (versione 2.4.5) manca la classe genitore?

class GrandParent { 
    String init() { 
     return "GrandParent init, " 
    } 
} 

class Parent extends GrandParent { 
    String init() { 
     return super.init() + "Parent init, " 
    } 
} 

class ChildInitAndVisit extends Parent { 
    String init() { 
     return super.init() + "Child init" 
    } 

    String visit() { 
     return super.init() + "Child visit" 
    } 
} 

class ChildVisitOnly extends Parent { 
    String visit() { 
     return super.init() + "Child visit" 
    } 
} 

e poi li utilizzano in questo modo:

iv = new ChildInitAndVisit() 
println "ChildInitAndVisit - calling init() -> ${iv.init()}" 
println "ChildInitAndVisit - calling visit() -> ${iv.visit()}" 

v = new ChildVisitOnly() 
println "ChildVisitOnly - calling visit() -> ${v.visit()}" 

mi sarei aspettato di vedere:

ChildVisitOnly - calling visit() -> GrandParent init, Parent init, Child visit 

come l'uscita dell'ultimo println. Invece vedo:

ChildVisitOnly - calling visit() -> GrandParent init, Child visit 

Ciò è in contrasto con il comportamento della classe ChildInitAndVisit e diverso per il comportamento sotto le vecchie versioni di Groovy - ho controllato 2.3.4.

È un bug di Groovy? O dovrei fare qualcosa di diverso?

risposta

1

Credo che questo sia il comportamento multi-methods (runtime/dynamic dispatch) di Groovy. Al momento dell'esecuzione, viene utilizzato init() da GrandParent anziché init() da Parent.

Un modo per utilizzarlo in modo Java (invio in compilazione) consiste nell'utilizzare @CompileStatic nella classe ChildVisitOnly.

@CompileStatic 
class ChildVisitOnly extends Parent { 

    String visit() { 
     return super.init() + "Child visit" 
    } 
} 

Sopra avrebbe dato il risultato che ci si aspetta.

Un altro approccio sarebbe quello di utilizzare init() o this.init() in ChildVisitOnly esplicitamente invece di @CompileStatic per forzare l'uso di init() da Parent.

class ChildVisitOnly extends Parent { 

    String visit() { 
     return init() + "Child visit" 
    } 
} 

devia Questo, ovviamente, dal comportamento da Groovy 2.3.4 ma sono ancora trovare un problema correlato che si concentra su questa differenza. Sono curioso di vedere se qualcun altro può indicarmi un difetto a causa del quale il comportamento è cambiato. :)

+0

I metodi multimodali basati sull'istanza utilizzati da Groovy indicano che i metodi da sottoclassi diventano visibili nell'ambito della classe padre quando si considera una chiamata di metodo nella classe padre, mentre si lavora su un'istanza della classe figlio. ma i metodi multimodali non sovrascrivono i metodi nel senso di Java. Il che significa che il metodo init in ChildVisitOnly deve essere di Parent, non di GrandParent. Groovy semplicemente non riesce a capire, che se scrivi 'super.init()' e non sovrascrivi il metodo init() che non dovrebbe prendere la classe genitrice della classe dichiarante del metodo init – blackdrag

2

A mio parere è un bug. in ChildVisitOnly deve chiamare Parent # init().

+0

Ho archiviato https: // issues .apache.org/jira/browse/GROOVY-7679 come segnalazione di bug – blackdrag

Problemi correlati