2009-10-06 2 views
2

Disons que j'ai paquets:Est-il possible d'accéder à un autre package sans le modificateur public?

com.mycomp.packone 
com.mycomp.packtwo 

Est-il possible pour moi d'accéder aux membres protégés d'une classe à PackOne d'une classe dans packtwo, mais pas permettre aux utilisateurs publics de le faire? La seule façon dont je peux penser est avec un accès protégé et en utilisant une sous-classe. Mais cela ne fait que déplacer le problème dans la sous-classe, parce que je voudrais aussi avoir les mêmes restrictions d'accès. Le contexte pour ceci est que nous sommes en train de refondre notre API principale et que nous voulons la rendre plus modulaire. En ce moment, tout est dans un paquet géant. Je n'étais pas ici pour cette conception, mais je suppose que c'est parce qu'il y a beaucoup d'utilisation protégée.

+0

Attendre les modules JDK7? –

Répondre

0

Le modificateur protected est votre seule option pour l'instant (le JDK7 n'est pas encore sorti). Comme vous l'avez dit, cela permet toujours aux sous-classes d'autres paquets d'accéder aux membres protégés. Vous pouvez empêcher le sous-classement en déclarant vos classes comme final mais je ne suis pas sûr que ce soit compatible avec votre cas d'utilisation. Il est également important de garder à l'esprit que les modificateurs d'accès en Java sont simplement des suggestions et facilement contournés par la réflexion.

1

Les paquets Java sont sévèrement limités (IMHO) en ce qu'il n'y a pas de traitement spécial pour la hiérarchie des paquets et le confinement entre eux. Chaque paquet est indépendant et la notation de point est pour les yeux humains seulement. La possibilité de limiter l'accès à des clients spécifiques est également cassée (comment cela me fait souhaiter parfois le mécanisme d'amitié de C++ ...)

AFAIK, c'est votre seule option pour l'instant jusqu'à ce que Java 7 arrête les choses. Une chose que vous pourriez envisager si (si votre projet s'adapte) est d'utiliser quelque chose comme OGSI. C'est l'infrastructure de modularisation et d'exportation vous permet de faire des choses qui sont plus affinées que ce que le langage permet.

0

Comme Asaph dit, briser les règles en utilisant la réflexion (utiliser getDeclaredMethod pour une méthode au lieu d'un champ):

package com.mycomp.packone; 

public class Introvert { 
    protected String secret = "TOP SECRET!"; 
} 

package com.mycomp.packtwo; 

import java.lang.reflect.Field; 

public class Extrovert { 
    public String talk(){ 
     return this.getSecret(); 
    } 

    @SuppressWarnings("unchecked") 
    protected String getSecret(){ // everybody in packtwo can call me! 
     try { 
      Class introvertClass = Class.forName("com.mycomp.packone.Introvert"); 
      Object introvert = introvertClass.newInstance(); 
      Field secretField = introvertClass.getDeclaredField("secret"); 
      secretField.setAccessible(true); 
      return (String) secretField.get(introvert); 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 
    } 

    public static void main(String[] args){ 
     Extrovert extrovert = new Extrovert(); 
     System.out.println(extrovert.talk()); 
    } 
} 
0

envisagerez la conception de votre API pour avoir des API « externes » et « internes ».

Alors que vous ne pouvez pas le faire en utilisant les modificateurs d'accès Java natives, vous pouvez emballer vos classes à l'aide:

package com.mycomp 
package com.mycomp.internal 

Dans package com.mycomp, vous publiez vos API publiques qui permettent aux utilisateurs « public » dépend de; la plupart du temps, il y a plus d'interfaces que de classes dans ce paquet.

com.mycomp.internal package est l'endroit où vous implémentez la plupart des interfaces trouvées dans com.mycomp. Nommer un package interne indique aux utilisateurs que les classes du package sont internes à l'API et que le choix des packages internes risque de casser leur code dans les versions ultérieures. De plus, si vous pouviez utiliser OSGi, vous ne pouvez exporter que le paquet com.mycomp, rendant ainsi com.mycomp.internal effectivement "caché" du reste du monde.

FWIW, mockito utilise cette méthode d'emballage pour son API.

L'inconvénient de cette méthode est le recours à une convention.

+0

Je penche pour cette solution à ce stade. OSGi semble prometteur pour la modularité, mais nous envoyons cette API aux clients et je ne suis pas sûr de l'impact et de l'augmentation des exigences OSGi sur eux – user26270

+0

@ codeman73: Les jarres compatibles OSGi peuvent être utilisés comme des jarres ordinaires; par conséquent, même si vos clients n'adoptent pas OSGi, ils ne seront pas affectés. En outre, vous pouvez également utiliser la convention d'empaquetage "externe/interne" sans adopter également OSGi. – shaolang

Questions connexes