为什么方法和属性的可见性很重要?

zii*_*web 43 php oop encapsulation visibility

为什么不能让所有方法和属性从任何地方(即public)可以访问?

如果我将属性声明为?你能一个我可以遇到的问题的例子public吗?

Mar*_*c B 146

把麦当劳想象成一个对象.有一个众所周知的公共方法来订购BigMac.

在内部会有几个其他的调用来实际获取用于制作Bigmac的材料.他们不希望您知道他们的供应链是如何运作的,所以您得到的只是公共Gimme_a_BigMac()电话,永远不会允许您访问Slaughter_a_cow()Buy_potatoes_for_fries()方法.

对于你自己的代码,没有人会看到,继续公开.但是,如果您正在为其他人重复使用库,那么您可以保护内部细节.这让麦当劳可以自由地改用Scotty光束而不是打电话给卡车运输公司来陆续运送肉类.最终用户永远不会知道差异 - 他们只是得到了他们的BigMac.但内部一切都可能从根本上改变.

  • 我认为这根本不是一个荒谬的比喻.毕竟,麦当劳的_is_对象和'Gimme_a_BigMac()`和`Slaughter_a_cow()`确实是方法.:)此外,如果麦当劳决定使用他们自己的马铃薯农场,内部的,私人/受保护的方法`Buy_potatoes_for_fries()`将改为`Pick_potatoes_for_fries()`,公众甚至不会注意到这一变化.+1代表一个很好的比喻. (52认同)
  • 应该-1表示麦当劳的汉堡是由实际的肉制成的. (44认同)
  • 尽管这个例子很荒谬,但它实际上是一个很好的描述,尤其是后来的库描述.创建API,我经常觉得能够保持相同的外部控件(`public`方法)是非常宝贵的,同时彻底检修内部控件(`private`或`protected`方法)以提高网站性能,同时提供相同的依赖响应. (4认同)
  • @anthony pegram:有趣的是,有两个RottenRonnie正在进行装修,两个都在升级下水道.我不确定这是为了增加处理......还是增加原料摄入量:p (4认同)
  • 很好的比喻,如果没有其他人能看到你的代码,那么它仍然很重要,因为你会看到你的代码.它允许您将应用程序分成可以在不破坏应用程序其余部分的情况下进行更改的组件.这是关于阻止自己调用一种你不想在特定环境之外调用的方法. (2认同)

Eri*_*ert 45

为什么不能让所有方法和属性都可以从任何地方(即公共)访问?

因为那太贵了.

每一个公共的方法,我做了仔细的设计,然后批准由建筑师团队,它已被执行在任意敌对或越野车呼叫者面对强大的,它必须经过全面测试,在测试过程中发现的所有问题必须有回归套件添加,该方法必须被记录,该文档已被转换成至少12种不同的语言.

最大的成本是:方法必须保持,不变,永远,永远,阿门.如果我在下一个版本中决定我不喜欢该方法所做的那样,我就无法改变它,因为客户现在依赖它.打破公共方法的向后兼容性会给用户带来成本,我不愿意这样做.使用糟糕的设计或实施公共方法会给下一版本的设计人员,测试人员和实施者带来高成本.

公共方法很容易花费数千甚至数万美元.在课堂上制作一百个,那就是一百万美元的课程.

私人方法没有这些费用.明智地花钱给股东; 尽可能让一切都变得私密.

  • @Roman R.:那些人正在使用他们的代码完全受信任的事实来公开其他类的内部实现细节.如果您要明确使用您的权限来覆盖安全系统,您将对可怕的事情负责. (3认同)
  • NikiC:你没有支付这些钱; 你节省了这些钱.在这个梦想世界中,如果你把一切都公之于众,你就会得到负薪水! (3认同)
  • +1我真的很想为每一种我不公开的方法付出"数千甚至数万美元":P (2认同)

jan*_*cha 12

将可见范围视为信任的内部圈子.

以自己为例,考虑哪些活动是公开的,什么是私人或受保护的.有许多事情你没有委托给任何人代表你做.有一些是很好的其他触发器,有些访问受限.

同样,在编程中,范围为您提​​供了创建不同信任圈的工具.此外,让事物变得私密/受保护,让您更好地控制正在发生的事情.例如,您可以允许可以扩展某些代码的第三方插件,同时可以限制它们可以走多远的范围.

因此,为了概括,范围可以为您提供额外的安全级别,并使事情更加有条理.


Dan*_*ite 10

因为这违反了封装的概念,这是OOP的一个关键原则.


Pro*_*tic 9

你说,你冒着风险吗?

<?php

class Foo
{
    /**
     * @var SomeObject
     */
    public $bar;
}
Run Code Online (Sandbox Code Playgroud)

您的代码声明$bar应包含对象instanceof SomeObject.但是,使用您的代码的任何人都可以

$myFoo->bar = new SomeOtherObject();
Run Code Online (Sandbox Code Playgroud)

...而依赖于Foo :: $ bar的任何代码SomeObject都会破坏.使用getter和setter以及受保护的属性,您可以强制执行此期望:

<?php

class Foo
{
    /**
     * @var SomeObject
     */
    protected $bar;

    public function setBar(SomeObject $bar)
    {
        $this->bar = $bar;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在你可以确定任何时候设置Foo :: $ bar,它都将是一个对象instanceof SomeObject.