与大多数其他OOP语言一样,在php中也有可见性修饰符。 这些是关键字public,protected和private。 但是它们仅适用于属性,方法或常量。 这些修饰符与封装数据的能力密切相关。 值得注意的是,在诸如Java,C#之类的语言中,请转到( https://golang.org/doc/go1.4#internalpackages ),红宝石( https://habr.com/post/419969/ ),水晶( https ://crystal-lang.org/reference/syntax_and_semantics/visibility.html ),可以限制包(packages)或类\类型的范围。 在php中,没有办法限制类的范围-任何其他类都可以访问任何连接的类。 但是,您可以使用一些技巧来模拟此功能。
为什么可能需要类级隐藏:
- 库的服务类(帮助程序)-不要用无意义的内部类来填充库API。
- 隐藏“业务逻辑”内部对象的封装,例如,禁止直接生成依赖对象,而绕过更通用的类。
另外,我们可以将“大”类的划分区分为小对象。 限制单个方法和类的复杂性(和行数)是一种很好的做法。 这里的行数是class方法或class本身承担不必要责任的标志之一。 重构公共方法时,我们将其一部分移至受私有\受保护的方法。 但是,当由于某种原因而导致类增长并且我们从中分离出一个单独的实体时,这些受非常私有\受保护的类将被转移到一个单独的类中,从而我们间接地开放了对以前限于一个类范围的方法的访问。
现在,模拟掩饰本身的实际方法。
使用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 final class PrivateClass { private $allowedConsumer = 'AllowedPrivateClassConsumer'; public function __construct() { $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 )。 在保护方法中描述了匿名类之后,我们试图将其隐藏。 为了不弄乱函数内部类的定义,可以在一个单独的文件中将其“抽象”描述为“私有”类,并已在匿名类的定义中对其进行了扩展。 使用此方法的一个很好的示例是此链接( https://markbakeruk.net/2018/06/25/using-php-anonymous-classes-as-package-private-classes/ )。
根据发现的资料,很明显,隐藏类的功能在某种程度上是需要的(并且存在于多种语言中),但是其使用的实践非常有限,这可能是由于缺乏各种“最佳实践”中对示例的描述,模板的集合和类似来源所致。 我认为这很奇怪,它强调隐藏对象的内部方法和属性,但是几乎没有人关注这样一个事实,即以实用程序库类或域域形式存在的更大的逻辑代码段仍保留在全局可见性空间中。