2010-11-25 4 views
8

Supposons que j'ai ce code Scala:Pourquoi les membres de mon objet compagnon imbriqué ne sont-ils pas automatiquement visibles dans la classe?

object Outer { 

    object Inner { 
    val B = "B" 
    } 
    class Inner { 
    def b = B 
    } 
} 

je me attends à ce compiler, mais B ne peut pas être accessible à partir de la définition de b. Je dois ajouter import Inner._ dans class Inner pour le faire fonctionner. Pourquoi donc? L'objet compagnon Inner n'est-il pas défini correctement?

+0

Je suis venu ici * encore * (après avoir oublié la chose), montrant à quel point ce problème peut être important pour les nouveaux arrivants. Je pense que le 'Outer' ne joue aucun rôle dans la question; c'est tout à fait pareil même sans. Merci d'avoir demandé ça! – akauppi

Répondre

6

Ce n'est pas supposé fonctionner de cette façon - l'utilisation de import Inner._ est un comportement cohérent. Généralement, l'objet compagnon est nécessaire, si vous souhaitez obtenir un comportement similaire à celui des membres statiques de Java. En général, l'objet compagnon est nécessaire. Scala façon est de déplacer tous les membres statiques loin à un objet singleton, avec l'avantage que memebers privé/protégé d'une classe d'accompagnement sont accessibles depuis le:

object Outer { 

    object Inner { 
    def print(inner: Inner) = inner.B // compiles! 
    }  
    class Inner { 
    private val B = "B" 
    }  
} 

Vous pouvez utiliser l'objet compagnon comme une usine pour la classe avec un constructeur privé:

scala> object Outer { 
    | 
    | object Inner { 
    |  def newInstance = new Inner() 
    | } 
    | class Inner private() { 
    |  private val B = "B" 
    | } 
    | } 
defined module Outer 

scala> Outer.Inner.newInstance 
res1: Outer.Inner = [email protected] 

scala> new Outer.Inner 
<console>:7: error: constructor Inner cannot be accessed in object $iw 
     new Outer.Inner 
    ^
+0

Je voudrais définir B comme une constante, utilisée dans la classe Outer.Inner et aussi accessible au monde extérieur comme Outer.Inner.B. J'étais sous l'impression que je n'avais pas besoin de l'import si Inner n'était pas imbriqué, mais je vois que je me suis trompé, car mon exemple ne compile pas non plus si je supprime la classe Outer ... Alors quoi de neuf? pour définir des constantes, semblable à la 'public static final String B =" B ";' que j'écrirais en Java? –

+0

Vous ne trouvez pas un problème -> https://gist.github.com/715219 –

+0

OK, je viens de confirmation besoin que j'ai besoin l'importation supplémentaire. C'est bien par moi; Je pensais juste que les membres étaient automatiquement importés dans des objets/classes compagnons. –

11

Si les membres de l'objet compagnon seraient importées dans la classe, il pollue l'espace de noms de la classe sans que le programmeur pouvoir ce controle. Cela pourrait ne pas être si mauvais (mais toujours mauvais) avec des valeurs mais je ne voudrais vraiment pas voir cela avec des fonctions. Il suffit de penser à apply() ou aux fonctions dont vous héritez des traits (les deux cas où vous ne pouvez pas changer le nom sans perdre quelque chose). Si ces fonctions étaient automatiquement importées dans votre espace de noms de classes, le compilateur ne saurait pas lequel utiliser. Donc, si la classe et l'objet avait une fonction func() vous finirez par écrit this.func() dans vos classes code juste pour vous assurer que l'on appeler.

donc voir comme une possibilité de garder votre espace propre. Vous pouvez toujours le polluer en utilisant import Inner._

+0

Bonne justification de la raison pour laquelle vous avez besoin de l'importation. Fait beaucoup de sens. –

Questions connexes