Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP中的类方法访问控制_Php_Oop - Fatal编程技术网

PHP中的类方法访问控制

PHP中的类方法访问控制,php,oop,Php,Oop,当对象方法用于不同的上下文(我的系统中的API)时,我需要组织对对象方法的某种访问控制。下面是代码示例: class A { public function doA(){} public function doB(){} } class APIAClient { public function getA() { return new A(); } } class

当对象方法用于不同的上下文(我的系统中的API)时,我需要组织对对象方法的某种访问控制。下面是代码示例:

    class A
    {
      public function doA(){}
      public function doB(){}
    }

    class APIAClient
    {
      public function getA()
      {
        return new A();
      }
    }

    class APIBClient {
      public function getA()
      {
        return new A();
      }
    }
在APIAClient中,对象A应同时具有doA()和doB()方法,但在APIBClient中不应具有doB()方法

现在我已经实现了ApibClientApproxy(由APIBCleint->getA()返回)

但可能有一种更好的模式可以解决我的问题,而不必为每个上下文(即API)使用额外的代理对象。我正在考虑在特定的上下文中使用允许的方法列表的magic uu调用方法,但是magic调用是一个很难做的文档,文档是我的应用程序中的重点(API应该被很好地文档化)


谢谢

您可以在这里使用继承,如下所示:

class A {
    public function doA() {
        // do something here
    }
}

class B extends A {
    public function doB() {
        // do something here
    }
}

class APIAClient
{
    public function getObj() {
        return new B();
    }
}

class APIBClient {
    public function getObj() {
        return new A();
    }
}

这样,当您在APIAClient上调用
getObj()
时,它将返回一个
B
的实例,该实例既有
doA()
又有
doB()
。但是,当您在
APIBClient
上调用它时,您将返回一个
A
的实例,该实例只有
doA()

,而不是继承,您可以通过traits使用组合(在PHP5.4中介绍)

首先定义特征

trait A {
  public function doA() {
    // do something here
  }
}

trait B {
  public function doB() {
    // do something here
  }
}
然后在类声明中使用这些特性

class APIAClient {
  use A, B

}

class APIBClient {
  use A
}

您不能根据创建实例的时间和方式来更改类(当然,不是真的)
您可以使用一种黑客解决方法(但我建议不要使用)

因此,如果将falsy值传递给a的构造函数(在
APIBClient
中),
doB
将抛出一个错误。但是,我也建议使用继承:

class AB
{
    public function doA()
    {
        //both B and B share this method
    }
}
class B
{//nothing atm
}
class A
{
    public function doB()
}
让您的
APIAClient
返回
new a()
,而
APIBClient
返回
B
类的新实例。
使用类型提示时,您只需检查
AB
实例:

public function doSomething(AB $instance)
{
    if ($instance instanceof A)
    {
        return $instance->doB();
    }
    return $instance->doA();
}

或者,当不依赖于类型提示和类型检查时,您可以始终使用许多函数中的一个,如
method\u exists

谢谢您的回答!但它不适合我-我没有层次访问模型,换句话说:doA()在APIAplha和APIBeta中可能可以访问,但在APIGamma中不可以访问,但在APIGamma中应该可以访问doB(),这在APIAplha/Beta中是不允许的,所有这些方法加上doC()应该在Apideta中可以访问。哦,可爱的特性:)但不幸的是,我只限于PHP5.3。@Zuker:你绝对不可能升级到5.4吗?因为我建议的特质和模式的结合会让事情变得容易得多。看到你在xbonez回答下面的评论,我想说我的回答确实允许你这样做(例如,您可以定义一个类
C
a
继承。它仍然是
AB
的一个实例,但将同时继承
AB
a
的方法,您也可以定义一些特定于类的方法。但过一段时间后,您将很难跟踪事物。特性确实有助于提升。)rcome单一继承的局限性
class AB
{
    public function doA()
    {
        //both B and B share this method
    }
}
class B
{//nothing atm
}
class A
{
    public function doB()
}
public function doSomething(AB $instance)
{
    if ($instance instanceof A)
    {
        return $instance->doB();
    }
    return $instance->doA();
}