我想要一个方法只能被特定类的对象调用

时间:2010-06-02 16:18:42

标签: design-patterns oop

假设你有这个课程:

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

我希望方法setNumber只能由特定类的对象调用。 是否有意义?我知道这是不可能的,不是吗?哪些是设计方案? 一些众所周知的设计模式? 抱歉这个愚蠢的问题,但我在OO设计上有点生疏。

编辑:我应该更清楚。抱歉。 我知道setNumber只能由类A的对象调用。我希望只有特定类的对象(具有对A类对象的引用)才能调用

classAObj.setNumber(n);

3 个答案:

答案 0 :(得分:1)

通过使该方法成为类“A”的成员,它只能由该类的对象调用。

因此,如果您有另一个类“B”的对象,则它无法调用setNumber,因为该方法不存在。

或者我错过了你的问题?

看来我有。

如果你有两个其他类“C”和“D”,它们都持有对“A”实例的引用,那么这是一个不同的问题。

我无法想到这样做的“好”方式。我唯一想到的就是:

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

然后当你致电setNumber时,你有:

objectA.setNumber(this, 23);

但是,这并没有阻止代码的编写者创建一个类型为“C”的对象将其传递给方法:

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

答案 1 :(得分:1)

假设您希望setNumber仅由班级AllowedSetNumber调用。一种可能的解决方案是强制要求您将AllowedsetNumber的实例作为参数传递,例如

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

那么问题就变成了,我如何阻止任何人创建AllowedSetNumber实例。这更容易确定 - 你可以用对象工厂做到这一点。使AllowedSetNumber包的构造函数成为私有的,甚至是私有的工厂方法。

另一个不需要更改方法签名的替代方法是使用与java SecurityManager相同的线程本地安全上下文。这可以通过在对象请求权限时分析堆栈跟踪来实现,因此可以对调用代码进行身份验证,然后根据安全策略进行授权。

请参阅java.security.PrivilegedAction<T>

答案 2 :(得分:0)

我需要澄清一下“特定类”究竟是什么意思......但我希望我正确解释,因为你只希望类A的实例能够调用该方法。

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

在这种情况下,A类的任何实例都可以调用方法:

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

但是,您将无法将A.setNumber()称为静态方法,而与实例无关。

如果只希望派生类(来自任何程序集)能够调用它:

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

public class B : A
{
}

在这种情况下,B类 A的任何实例都可以调用setNumber(),但没有其他类可以查看或访问它。

如果您只希望同一程序集中的所有实例类都能够调用它:

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

在这种情况下,与类'A'在同一程序集中的任何类都可以调用setNumber(),就好像它是一个公共属性一样,但是其他程序集中包含的类都不能看到它或引用它们它。在VB.NET中,内部与'朋友'相同。

如果您只希望同一程序集中的派生类能够调用它:

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

public class B : A
{
}

在这种情况下,无论程序集如何,B类 A的任何实例都可以查看和引用setNumber();并且与A类在同一个程序集中的任何类都能够看到它或引用它,就好像它是公共的一样。

我认为这涵盖了每个选项......