0

Suppose you have this class:

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

I'd like the method setNumber could be called only by objects of a specific class. Does it make sense? I know it is not possible, is it? Which are the design alternatives? Some well known design pattern? Sorry for the silly question, but I'm a bit rusty in OO design.

EDIT: I should be more clear. Sorry. I know setNumber can be invoked only by objects of class A. I'd like that only objects of a specific class (having a reference to class A objects), could call

classAObj.setNumber(n);
mp.
  • 521
  • 3
  • 9
  • 1
    What is the deeper reason why you want to guard this method? Security, user rights, something else? – mdma Jun 02 '10 at 16:23
  • Can you clarify the situation in which it would be allowable to call it? i.e. when you say "specific class", would that class be deriving from class A, would it be in the same assembly as class A or would it only be instances of class A? – BenAlabaster Jun 02 '10 at 16:33
  • You might want to take a look at this question that ask basically the same thing: http://stackoverflow.com/questions/1609472/friend-class-with-limited-access – n1ckp Jun 02 '10 at 16:38
  • Class B doesn't derive from ClassA. The reason is that the only class that has all the information needed to change the number is ClassB. – mp. Jun 02 '10 at 16:56

3 Answers3

1

Well by making the method a member of the class "A" it can only be called by objects of that class.

So if you had another object of class "B" then it couldn't call setNumber because that method wouldn't exist.

Or have I missed something in your question?

It appears I have.

If you have two other classes "C" and "D" both of which hold a reference to an instance of "A" then that's a different problem.

I can't think of a "nice" way of doing this. The only thing that springs to mind is to have:

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;
        }
    }
}

Then when you call setNumber you'd have:

objectA.setNumber(this, 23);

However, that doesn't stop the writer of the code creating an object of type "C" to pass that into the method:

C objectC = new C();
objectA.SetNumber(objectC, 23);
ChrisF
  • 134,786
  • 31
  • 255
  • 325
  • I think the poster is imagining a scenario where a bunch of different classes have references to instances of class A, but only some of them should be able to call that particular method (depending of the class of the container). – Jacob Mattison Jun 02 '10 at 16:22
  • in the scenario you're interpreting, I would probably use something like if (new[] { typeof(C), typeof(D) }.Contains(sender.GetType())){ //Do stuff } – BenAlabaster Jun 02 '10 at 17:01
1

Let's say you want setNumber to be only called by class AllowedSetNumber. One possible solution is to mandate that you pass an instance of AllowedsetNumber as a parameter, e.g.

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

So then the question becomes, how can I stop anyone from creating an AllowedSetNumber instance. This is quite a bit easier to nail down - you can do that with object factories. Making the constructor of AllowedSetNumber package private, or even private with a factory method.

Another alternative, that doesn't require changing the method signature, is to have a thread-local security context in the same vein as the java SecurityManager. This works by analysing stack traces when an object requests permission, and so the calling code can be authenticated, and then authorized according to the security policy.

See java.security.PrivilegedAction<T>

mdma
  • 56,943
  • 12
  • 94
  • 128
  • Another way would be to reference the caller through some mechanism similar to reflection if it is available in the framework being used. – BenAlabaster Jun 02 '10 at 16:51
0

I need some clarification as to what exactly you mean by "specific classes"... but I'm hoping that I'm interpreting correctly in that you only want instances of class A to be able to call the method.

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

In this case, any instances of class A can call the method:

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

However, you wouldn't be able to refer to A.setNumber() as if it were a static method - without relation to an instance.

If you want only derived classes (from any assembly) to be able to call it:

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

public class B : A
{
}

In this case, any instances of class B or A could call setNumber(), but no other classes could see or access it.

If you only want all instances classes within the same assembly to be able to call it:

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

In this case, any classes within the same assembly as your class 'A' will be able to call setNumber() as if it were a public property, but no classes contained in other assemblies will be able to see it or reference it. In VB.NET internal is the same as 'Friend'.

If you only want derived classes within the same assembly to be able to call it:

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

public class B : A
{
}

In this case, any instances of class B or A regardless of assembly can see and reference setNumber(); and any classes within the same assembly as class A will be able to see it or reference it as if it were public.

I think that covers each of the options...

BenAlabaster
  • 39,070
  • 21
  • 110
  • 151