プライベートクラス。 PHPでの非表示

phpでは、他のほとんどのOOP言語と同様に、可視性修飾子があります。 これらは、キーワードpublic、protected、およびprivateです。 ただし、プロパティ、メソッド、または定数にのみ適用されます。 これらの修飾子は、データをカプセル化する機能と密接に関連しています。 java、C#、go( https://golang.org/doc/go1.4#internalpackages )、ruby( https://habr.com/post/419969/ )、crystal( httpsなどの言語では注意が必要です://crystal-lang.org/reference/syntax_and_semantics/visibility.html )パッケージ(パッケージ)またはクラス\タイプの範囲を制限することができます。 PHPでは、クラスのスコープを制限する方法はありません。接続されたクラスは他のクラスからアクセスできます。 ただし、いくつかのトリックを使用してこの機能をエミュレートできます。







クラスレベルの非表示が必要な理由:









それとは別に、「大きな」クラスのパーティションを小さなオブジェクトに区別できます。 個々のメソッドとクラスの両方の複雑さ(および行数)を制限することをお勧めします。 ここでの行数は、クラスメソッドまたはクラス自体が不必要な責任を負うマーカーの1つになります。 パブリックメソッドをリファクタリングするとき、その一部をプライベート\プロテクトメソッドに移動します。 しかし、何らかの理由でクラスが大きくなり、別のエンティティを分離すると、これらの非常にプライベートな\保護されたクラスが別のクラスに転送されるため、以前は1つのクラスのスコープによって制限されていたメソッドへのアクセスが間接的に開かれます。







今、隠蔽自体をエミュレートする実際の方法。







コード署名契約のレベルで



PHPDocコメントを使用して、クラス、特性、またはインターフェースをinternal



としてマークできます( http://docs.phpdoc.org/references/phpdoc/tags/internal.html )。 ただし、一部のIDE(PhpStormなど)はこのようなラベルを理解できます。







ランタイム情報を使用する



実行時に、クラスコンストラクターの呼び出し元を確認できます。 たとえば、 debug_backtrace



メソッド( http://php.net/manual/ru/function.debug-backtrace.php )を使用するか、同様のXdebug機能を使用してdev \ test環境でコードを制御します。 正式なソリューションの例はこちらです( https://coderwall.com/p/ixvnga/how-emulates-private-class-concept-in-php )。







debug_backtraceを使用する
 /** * The private class */ final class PrivateClass { /** * defines the only class able to instantiate the current one * * @var string */ private $allowedConsumer = 'AllowedPrivateClassConsumer'; /** * constructor * * @throws Exception */ public function __construct() { /** * here comes the privacy filter, it could be extracted to a private method * or to a static method of another class with few adjustments */ $builder = debug_backtrace(); if (count($builder) < 2 || !isset($builder[1]['class']) || $builder[1]['class'] !== $this->allowedConsumer) { throw new Exception('Need to be instantiated by '.$this->allowedConsumer); } } }
      
      





匿名クラスを使用する



phpの比較的新しい機能は、匿名クラス( http://php.net/manual/ru/language.oop5.anonymous.php )です。 protectedメソッド内で匿名クラスを記述することにより、それを隠そうとします。 関数内でクラスの定義を混乱させないために、別のファイルで「プライベート」クラスを抽象として記述し、匿名クラスの定義で既にそれを展開できます。 このメソッドを使用する良い例は、このリンクにあります( https://markbakeruk.net/2018/06/25/using-php-anonymous-classes-as-package-private-classes/ )。







発見された資料に基づいて、クラスを隠す機能がある程度要求されていることは明らかです(そして多くの言語に存在します)が、その使用方法は非常に限定されています。 私の意見では、オブジェクトの内部メソッドとプロパティを隠すことに重点が置かれているというのはかなり奇妙ですが、ユーティリティライブラリクラスまたはドメインドメインの形式のコードのより大きな論理部分がグローバルな可視性スペースに残っているという事実にほとんど誰も注意を払っていません。








All Articles