簡體   English   中英

PHP中的類方法訪問控制

[英]Class methods access control in PHP

當在不同的上下文(系統中的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()方法。

目前,我已經實現了APIBClientAProxy(由APIBCleint-> getA()返回)

   class APIBClientAProxy
   {
     private $a = new A;
     public function doA()
     {
       $this->a->doA()
     }
   }

但是可能有一種更好的模式可以解決我的問題,而無需為每個上下文(即API)使用額外的代理對象。 我正在考慮魔術__call方法以及在特定上下文中允許使用的方法的列表,但是魔術調用很難做文檔,而文檔是我應用程序中的重點(API的文檔應該很好地記錄下來)

謝謝!

除了繼承,您還可以通過特征使用組合(PHP 5.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
}

您可以在此處使用繼承,如下所示:

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

這樣,當你調用getObj()上APIAClient,它會返回一個實例B同時具有這doA()doB() 但是,當在APIBClient上調用它時,您將返回A的實例,該實例僅具有doA()

您不能根據創建實例的時間和方式來更改類(嗯,不是真的)。
您可以使用一種變通的解決方法(但我建議您反對)

class A
{
    private $_canDoB = null;
    public function __construct($doB = true)
    {
        $this->_canDoB = !!$doB;//force bool
    }
    public function doB()
    {
        if ($this->_canDoB === false)
        {
            throw new LogicError('You can\'t doB');
        }
    }
}

因此,如果將假值傳遞給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_exists

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM