2012-10-09 11 views
17

Perdón por el título pegadizo. ;-)No puedo hacer ningún paquete de clase privada en Scala?

Quiero crear una clase de paquete-privada con un método paquete-privada en Scala, por lo que mi clase se ve algo como esto:

package net.java.truevfs.ext.pace 

import ... 

private[pace] abstract class AspectController(controller: FsController) 
extends FsDecoratingController(controller) { 

    private[pace] def apply[V](operation: => V): V 

    ... // lots of other stuff 
} 

Sin embargo, si uso javap para comprobar cuál es el Scala compilador crea efectivamente, me sale algo como esto:

$ javap -classpath target/classes net.java.truevfs.ext.pace.AspectController 
Compiled from "AspectController.scala" 
public abstract class net.java.truevfs.ext.pace.AspectController extends net.java.truevfs.kernel.spec.FsDecoratingController implements scala.ScalaObject{ 
    public abstract java.lang.Object apply(scala.Function0); 
    ... 
} 

esto significa que aunque el compilador Scala podría respetar las restricciones de acceso, todavía podía llamar a esta clase de cualquier código Java, que es una violación clara de encapsulación.

¿Echo de menos algo? ¿Hay alguna manera de hacer que esto funcione según lo previsto?

+2

+1 por el título divertido –

Respuesta

15

Además de @ respuesta de Regis, la razón Scala compilador no hace que el paquete-privada de clase se debe a que por lo gobierna Scala puede acceder desde otros paquetes: a saber, sub-paquetes de net.java.truevfs.ext.pace. P.ej.

package net.java.truevfs.ext.pace.subpackage 
import net.java.truevfs.ext.pace.AspectController 

class Subclass extends AspectController { ... } 

es legal en Scala, pero en Java clases de net.java.truevfs.ext.pace.subpackage no se puede acceder a las clases del paquete-privada de net.java.truevfs.ext.pace.

+0

+1. En realidad iba a señalar lo mismo. –

+0

Buen punto - No sabía esto. –

+0

Bueno, esto en realidad significa que el concepto de una clase paquete privado no existe en Scala en absoluto. Es una lástima, porque para mí ha sido un elemento principal de mi conjunto de herramientas Java para fomentar la encapsulación (entiendo que esta protección solo funciona en el nivel de idioma de todos modos). –

9

No se echa en falta nada. Muchas de las restricciones de acceso en scala no tienen equivalente en Java ni en el nivel jvm. La información adicional está obviamente allí mismo en el archivo .class, pero está allí como anotaciones personalizadas que solo el compilador scala interpretará. El modelo de objetos scala solo puede coincidir parcialmente con el modelo de objetos jvm, y un compilador java solo verá este modelo parcial. Diría que el emparejamiento es bastante cercano y el compilador scala hace un muy buen trabajo en interoperabilidad java, pero nada es perfecto.

+0

lo pensé y reconoció la anotación @ scala.reflect.ScalaSignature en la clase. Sin embargo, lo que me preocupa es que esta es una clara violación de la encapsulación y hace que el uso de modificadores de acceso sea completamente inútil, siempre y cuando puedas llamar cualquier cosa desde el código Java. –

+3

Bueno, "sin sentido" en el mismo grado en que los modificadores de acceso en general no tienen sentido, ya que siempre se puede eludir a través de reflexión/punteros. – themel

+0

No llegaría tan lejos como para decir que puedes llamar "cualquier cosa" desde Java. Si haces 'apply' plain private (en lugar de private para' pace') entonces verás que el método está realmente marcado como privado en el archivo .class. Esto se debe a que el concepto de un método privado en scala y en java es exactamente el mismo, por lo que el compilador puede marcarlo como privado. Por otro lado, el concepto de un método privado para un paquete simplemente no existe en java/the jvm. –

1

No es realmente una respuesta correcta al 100% ...

Usted puede hacer un objeto de paquete si quiero hacer algunas cosas de lujo allí con una clase privada. El objeto del paquete se accede como cualquier otro paquete. La clase MyClass es un paquete privado para ese objeto de paquete. Sin embargo, no es un paquete privado.

package object com.jasongoodwin.foo { 
    private class MyClass 

    class AnotherClass { 
    val myClass = new MyClass 
    } 
} 
Cuestiones relacionadas