代码之家  ›  专栏  ›  技术社区  ›  mp.

我希望一个方法只能由特定类的对象调用

  •  0
  • mp.  · 技术社区  · 14 年前

    假设你有这个班:

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

    我想要这个方法 setNumber 只能由特定类的对象调用。 这有道理吗?我知道这是不可能的,是吗?哪些是设计备选方案? 一些著名的设计模式? 对不起,这个愚蠢的问题,但我的OO设计有点生疏。

    编辑:我应该更清楚。对不起的。 我知道setnumber只能由类A的对象调用。我希望只有特定类的对象(具有对类A对象的引用)可以调用

    classAObj.setNumber(n);
    
    3 回复  |  直到 14 年前
        1
  •  1
  •   mdma    14 年前

    假设你想要 setNumber 只能由类调用 AllowedSetNumber . 一种可能的解决方案是强制您通过 AllowedsetNumber 作为参数,例如

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

    那么问题就变成了,我如何才能阻止任何人创建 允许集编号 实例。这是相当容易确定-你可以这样做的对象工厂。使建造师 允许集编号 包私有,甚至用工厂方法私有。

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

    java.security.PrivilegedAction<T>

        2
  •  1
  •   ChrisF    14 年前

    好吧,通过使方法成为类“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;
            }
        }
    }
    

    当你打电话的时候 设置号 你会有:

    objectA.setNumber(this, 23);
    

    但是,这并不能阻止代码编写器创建“c”类型的对象,将其传递到方法中:

    C objectC = new C();
    objectA.SetNumber(objectC, 23);
    
        3
  •  0
  •   BenAlabaster    14 年前

    我需要澄清一下你所说的“特定课程”到底是什么意思…但我希望我的解释正确,因为您只希望类A的实例能够调用该方法。

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

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

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

    但是,如果引用.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中,内部与“friend”相同。

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

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

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

    我认为这涵盖了所有的选择…