2011-12-31 15 views
5

Estoy en una situación en la que tengo la necesidad de mezclar un rasgo definido en otro paquete. Para ayudar con las pruebas, un método protegido en este rasgo es un paquete calificado. Aquí está un ejemplo:Heredando un método protegido por paquete por una clase en un paquete diferente

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

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

Compilar esto con scalac 2.9.1 rendimientos:

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

Cambio de la "protegido [A]" en la clase Y para cualquier otro resultado modificador de acceso en este:

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) { } 

Mi pregunta es esta: Suponiendo que la definición de rasgo X no puede cambiar, ¿hay algún cambio en la clase Y que le permita extender el rasgo X? (conservando cierto nivel de acceso 'protegido')

Si esto no es posible, ¿existen otras estrategias de diseño recomendadas para evitar esto? (que no sea público 'método')

+0

Debo agregar que estoy tratando de responder la simple pregunta de si esto es imposible por diseño, de modo que la única (simple) manera de corregirlo es cambiar 'protegido [A]' a 'público'. Simplemente parece una subclase independientemente de si el paquete debería poder acceder. ¿o no? – nu11ptr

+0

Parece que la solución "correcta" aquí es dividir la definición de clase Y en una clase y un rasgo. Pondré el rasgo en un subpaquete de A, definiré allí el "método" y luego lo mezclaré con la clase Y. En el mundo real, A es "marketdata" y B es "intermediario", por lo que tiene sentido cuando finalmente tenemos una instancia de intermediario que también es un proveedor de datos para dividir esta funcionalidad, colocarla en un sub paquete de datos de mercado y mezclarla. De todos modos, este es probablemente un mejor diseño, ya que son dos preocupaciones completamente diferentes (manejo de pedidos vs. datos de mercado). – nu11ptr

Respuesta

2

Terminé resolviendo esto con un adaptador. Si bien no puedo cambiar el rasgo original, puedo agregar otro en el mismo paquete (pero por otras razones no tendría sentido colocar la clase Y en ese paquete). El 'adapterMethod' en la clase Y está calificado para el paquete B como un experimento, pero lo más probable es que esto no sea necesario para mi caso de uso. Las siguientes compilaciones en 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) { } 
    } 
} 

No estoy loco por esta solución, pero no está tan mal. La clase Y es una excepción, ya que el resto de las clases que usan el rasgo X están en el paquete A (la clase Y debe estar en el paquete B por muchas otras razones). Alguna mejor idea?

+0

¿Puede derivar B de A: "paquete A.B {clase Y ..."? – TechNeilogy

+0

Técnicamente, sí, pero sería arbitrario y "incorrecto" por muchas otras razones, ya que A y B no tienen nada que ver entre sí y hay muchas clases en cada una. Gracias por la sugerencia, sin embargo. – nu11ptr

+0

Actualización: Resulta que haré algo similar al dividir la clase Y entre los dos pacakages. – nu11ptr

Cuestiones relacionadas