2011-12-31 9 views
5

Sono in una situazione in cui è necessario mescolare un tratto definito in un altro pacchetto. Per facilitare il test, un metodo protetto in questo tratto è qualificato come pacchetto. Ecco un esempio:Ereditarietà di un metodo protetto da pacchetti con una classe in un pacchetto diverso

package A { 
    trait X { 
    protected[A] def method(arg: Int) 
    } 
} 

package B { 
    class Y extends A.X { 
    protected[A] def method(arg: Int) { } 
    } 
} 

compilazione questo con scalac 2.9.1 rendimenti:

test.scala:9: error: A is not an enclosing class 
    protected[A] def method(arg: Int) { } 

Modifica della "protetto [A]" in classe Y a qualsiasi altro risultato accesso modificatori in questo:

test.scala:9: error: overriding method method in trait X of type (arg: Int)Unit; 
method method has weaker access privileges; it should be at least protected[A] 
    override protected def method(arg: Int) { } 

La mia domanda è questa: supponendo che la definizione di tratto X non possa cambiare, c'è qualche modifica alla classe Y che consentirebbe di estendere il tratto X? (pur mantenendo un certo livello di accesso "protetto")

Se ciò non è possibile, ci sono altre strategie progettuali consigliate per ovviare a questo problema? (oltre a rendere pubblico il "metodo")

+0

Aggiungo che sto cercando di rispondere alla semplice domanda se questo sia impossibile in base alla progettazione, in modo tale che l'unico (semplice) modo di sistemare è quello di cambiare "protetto [A]" in "pubblico". Sembra solo una sottoclasse, indipendentemente dal pacchetto che dovrebbe essere in grado di accedere? o no? – nu11ptr

+0

Sembra che la soluzione "giusta" qui sia quella di suddividere la definizione di classe Y in una classe e un tratto. Metterò il tratto in un sottoprogetto di A, definirò il 'metodo' lì, e poi lo mescolerò con la classe Y. Nel mondo reale, A è 'marketdata' e B è 'broker', quindi ha senso quando finalmente abbiamo un'istanza broker che è anche un fornitore di dati per dividere questa funzionalità, inserirla in un sotto-pacchetto di dati di mercato e mischiarla. Questo è probabilmente un progetto migliore in ogni caso, poiché sono due preoccupazioni completamente diverse (gestione degli ordini rispetto ai dati di mercato). – nu11ptr

risposta

2

Ho risolto questo problema con un adattatore. Mentre non posso modificare il tratto originale, posso aggiungerne un altro nello stesso pacchetto (ma per altri motivi non avrebbe senso inserire la classe Y in quel pacchetto). Il 'adapterMethod' nella classe Y è qualificato per il pacchetto B come esperimento, ma molto probabilmente questo non è necessario per il mio caso d'uso. Il seguente compila in scala 2.9.1:

package A { 
    trait X { 
    protected[A] def method(arg: Int) 
    } 

    trait PackageAdapter { 
    protected[A] def method(arg: Int) { adapterMethod(arg) } 

    protected def adapterMethod(arg: Int) 
    } 
} 

package B { 
    class Y extends A.X with A.PackageAdapter { 
    protected[B] def adapterMethod(arg: Int) { } 
    } 
} 

Non sono pazzo di questa soluzione, ma non è così male. La classe Y è un po 'un caso di eccezione poiché il resto delle classi che usano il tratto X si trovano nel pacchetto A (la classe Y deve essere nel pacchetto B per molti altri motivi). Qualche idea migliore?

+0

Puoi derivare B da A: "pacchetto A.B {class Y ..."? – TechNeilogy

+0

Tecnicamente, sì, ma sarebbe arbitrario e 'sbagliato' per molte altre ragioni come A e B non hanno nulla a che fare l'uno con l'altro e ci sono molte classi in ciascuna. Grazie per il suggerimento però. Aggiornamento – nu11ptr

+0

: Risulterà che farò qualcosa di simile dividendo la classe Y tra i due pacakage. – nu11ptr

Problemi correlati