2010-06-02 3 views
0

Supposons que vous ayez cette classe:je voudrais une méthode à appeler uniquement par des objets d'une classe spécifique

 
public class A 
{ 
    private int number; 
    public setNumber(int n){ 
     number = n; 
    } 
} 

J'aimerais la méthode setNumber pourrait être appelée que par des objets d'une classe spécifique. Est-ce logique? Je sais que ce n'est pas possible, n'est-ce pas? Quelles sont les alternatives de conception? Un motif de conception bien connu? Désolé pour la question stupide, mais je suis un peu rouillé dans OO design.

EDIT: Je devrais être plus clair. Pardon. Je sais setNumber peut être invoqué que par des objets de classe A. Je voudrais que seuls les objets d'une classe spécifique (ayant une référence à des objets de classe A), pourrait appeler

 
classAObj.setNumber(n); 
+1

Quelle est la raison profonde pour laquelle vous voulez garder cette méthode? Sécurité, droits d'utilisateur, autre chose? – mdma

+0

Pouvez-vous clarifier la situation dans laquelle il serait permis de l'appeler? c'est-à-dire lorsque vous dites «classe spécifique», cette classe dériverait-elle de la classe A, serait-elle dans le même assemblage que la classe A ou serait-ce seulement des instances de la classe A? – BenAlabaster

+0

Vous pourriez jeter un oeil à cette question qui demande fondamentalement la même chose: http://stackoverflow.com/questions/1609472/friend-class-with-limited-access – n1ckp

Répondre

1

Disons que vous voulez setNumber être seulement appelé par classe AllowedSetNumber. Une solution possible consiste à exiger que vous transmettiez une instance de AllowedsetNumber en tant que paramètre, par ex.

public class A 
{ 
    private int number; 
    public setNumber(int n, AllowedSetNumber caller){ 
     number = n; 
    } 
} 

Alors la question devient, comment puis-je empêcher quiconque de créer une instance AllowedSetNumber. C'est un peu plus facile à clouer - vous pouvez le faire avec des usines d'objets. Rendre le constructeur du paquet AllowedSetNumber privé, ou même privé avec une méthode d'usine. Une autre alternative, qui ne nécessite pas de changer la signature de la méthode, est d'avoir un contexte de sécurité local de thread dans la même veine que le SecurityManager java. Cela fonctionne en analysant les traces de pile lorsqu'un objet demande l'autorisation, et ainsi le code appelant peut être authentifié, puis autorisé conformément à la politique de sécurité.

Voir java.security.PrivilegedAction<T>

+0

Une autre façon serait de référencer l'appelant par un mécanisme similaire à la réflexion s'il est disponible dans le cadre utilisé. – BenAlabaster

1

bien en faisant la méthode a membre de la classe "A", il ne peut être appelé que par des objets de cette classe. Par conséquent, si vous aviez un autre objet de la classe "B", il ne pouvait pas appeler setNumber car cette méthode n'existerait pas.

Ou ai-je raté quelque chose dans votre question?

Il semble que j'ai.

Si vous avez deux autres classes "C" et "D" qui contiennent toutes deux une référence à une instance de "A", alors c'est un problème différent.

Je ne peux pas penser à une "bonne" façon de le faire. La seule chose qui vient à l'esprit est d'avoir:

public class A 
{ 
    private int number; 
    public setNumber(object sender, int n) 
    { 
     if (sender.GetType() == C) // Not sure of the exact syntax here 
     { 
      number = n; 
     } 
    } 
} 

Quand vous appelez setNumber vous auriez:

objectA.setNumber(this, 23); 

Cependant, cela ne s'arrête pas l'auteur du code création d'un objet de type « C » pour passer que dans la méthode:

C objectC = new C(); 
objectA.SetNumber(objectC, 23); 
+0

Je pense que l'affiche imagine un scénario où un groupe de classes différentes ont des références à des instances de classe A, mais seulement certaines d'entre elles devraient être capables d'appeler cette méthode particulière (en fonction de la classe du conteneur). –

+0

Oui, c'est le scénario. –

+0

dans le scénario que vous interprétez, j'utiliserais probablement quelque chose comme si (new [] {typeof (C), typeof (D)} .Contains (sender.GetType())) {// Do stuff} – BenAlabaster

0

J'ai besoin des éclaircissements sur exactement ce que vous entendez par « classes spécifiques » ... mais je suis en espérant que j'interprète correctement ce que vous voulez que les instances de la classe A à être capable d'appeler la méthode.

public class A 
{ 
    private int number; 
    private void setNumber(int Number) 
    { 
    number = Number; 
    } 
} 

Dans ce cas, toutes les instances de la classe A peut appeler la méthode:

A myAinstance = new A(); 
myAinstance.setNumber(5); 

Cependant, vous ne seriez pas en mesure de se référer à A.setNumber() comme si elle était statique méthode - sans relation avec une instance.

Si vous souhaitez que les classes dérivées (de toute assemblée) pour pouvoir l'appeler:

public class A 
{ 
    private int number; 
    protected void setNumber(int Number) 
    { 
    number = Number; 
    } 
} 

public class B : A 
{ 
} 

Dans ce cas, les instances de la classe B ou A pourrait appeler setNumber(), mais pas d'autres classes pourraient voir ou y accéder.

Si vous ne souhaitez que toutes les instances des classes dans le même ensemble pour pouvoir l'appeler:

public class A 
{ 
    private int number; 
    internal void setNumber(int Number) 
    { 
    number = Number; 
    } 
} 

Dans ce cas, toutes les classes dans le même ensemble que votre classe « A » sera en mesure d'appeler setNumber() comme s'il s'agissait d'une propriété publique, mais aucune classe contenue dans d'autres assemblées ne pourra la voir ou la référencer. En VB.NET interne est le même que «ami».

Si vous ne souhaitez classes dérivées dans le même ensemble pour pouvoir l'appeler:

public class A 
{ 
    private int number; 
    protected internal void setNumber(int Number) 
    { 
    number = Number; 
    } 
} 

public class B : A 
{ 
} 

Dans ce cas, les instances de la classe B ou A quel que soit l'assemblage peut voir et setNumber de référence () et toutes les classes dans le même assemblage que la classe A pourront le voir ou le référencer comme s'il était public.

Je pense que cela couvre chacune des options ...

Questions connexes