【问题标题】:What is the point of OOP visibility in PHP when Closures and Reflections are available?当闭包和反射可用时,PHP 中的 OOP 可见性有什么意义?
【发布时间】:2018-06-29 08:59:20
【问题描述】:

在这里考虑这段代码:

final class TinkerWithMe {
    protected $key1 = 19;
    private $key2 = 88;
}

$class = new TinkerWithMe();

$getKeys = function() {
    return array($this->key1, $this->key2);
};

$oldKeys = $getKeys->call($class);

$newKey1 = 96;
$newKey2 = 42;

$setKeys = function() use ($newKey1, $newKey2) {
    $this->key1 = $newKey1;
    $this->key2 = $newKey2;
};

$setKeys->call($class);

既然您可以通过闭包或反射如此轻松地绕过 OOP 可见性,为什么还要为它烦恼?

有没有办法阻止我错过的这种事情?

【问题讨论】:

  • 可见性也传达了意图。

标签: php class oop reflection closures


【解决方案1】:

好问题!我想补充几点

在 OOP 语言中指定可见性的目的是:

  1. 显示属性和方法的用途。这是为了让开发人员清楚地了解如何访问/修改属性和方法,以决定是否扩展类。
  2. 在其各自类中设置的属性经过验证并设置为正确的值,无需检查属性类型即可在类中安全使用。
  3. 这不是保护数据免遭修改的万无一失的方法。

闭包的目的是将一个函数扔到一个变量或另一个函数中,以偶尔执行一些活动。您可以使用闭包,而不是在全局范围内将单独的部分代码用于偶尔执行一个操作并且稍后不查看它。

反射旨在内省对象以了解其属性、方法、类等。识别依赖关系很有用。 Larvel 使用反射来执行对象的依赖注入。

是的,正如您所说,您可以使用闭包和反射来解决可见性问题,但它应该被视为一种语言功能而不是设计缺陷,因为没有一种语言可以 100% 保护数据

【讨论】:

    【解决方案2】:

    可见性修饰符不是铁皮保护或确保任何类型的安全或任何类型的东西。它们是标记一段代码打算被使用的方式。

    当编写像类这样的一段代码时,其他代码段将与之耦合;这意味着您将编写其他代码来调用该类的方法或访问该类的属性。为了最大限度地减少与绝对必要的耦合,您需要使类的 public interface 尽可能小。当您将某个东西指定为public 时,您将其标记为“供一般用途”。然后,该公共部分应该相当稳定且不会更改,否则如果您更改它,您可能会破坏大量耦合代码。

    将某些东西标记为protectedprivate 将这些部分标记为不用于一般消费;它阐明了这些实现细节可能在未来发生变化,或者不应该被“不知道”的其他代码使用。这使您可以在以后根据需要更轻松地重构这些部分,并更好地了解其他部分可能因此而损坏。当外部代码在不完全理解它应该如何做的情况下不直接修改内部值时,它还有助于确保类的内部状态是一致的。

    PHP 将帮助您在一般情况下通过在天真地尝试“从外部”访问 protectedprivate 属性时抛出错误来尊重这些标记;这可以防止大多数意外使用和不必要的耦合。 PHP 不会向后弯腰以确保在所有可能的情况下这些属性都无法访问。如果你真的一心想拍自己的脚,那就这样吧。也许您出于测试目的需要这样做;绝对阻止您这样做会适得其反。

    mantra of Python

    我们都是同意这里的成年人。

    【讨论】:

    • 感谢您的回答。我想 PHP 可能是错误的语言,但考虑到有多少 CMS 解决方案和大型 3rd 方插件生态系统,有些东西是私有的,如果它们能保持私有状态会很好。说明不要轻易选择 3rd 方代码是多么重要。
    • 如果您的意思是“安全”中的“私有”:可见性修饰符不是正确的工具。几乎没有任何语言可以保护您免受在同一程序/线程/上下文中运行的代码的影响。是的,如果您选择运行某些代码,则必须信任该代码。如果您不信任代码,请不要运行它。
    猜你喜欢
    • 2014-10-25
    • 1970-01-01
    • 2015-04-27
    • 2017-07-04
    • 2015-09-02
    • 2010-11-20
    • 1970-01-01
    • 2011-07-25
    • 2011-11-09
    相关资源
    最近更新 更多