PHP5 保护变量背后的推理

Posted

技术标签:

【中文标题】PHP5 保护变量背后的推理【英文标题】:Reasoning Behind PHP5 Protected Variables 【发布时间】:2011-07-20 19:48:41 【问题描述】:

您能解释一下为什么我想在 php5 中的某些类变量和方法上使用“受保护”而不是“公共”或“私有”的原因是什么?我还没有找到一个我认为我需要“保护”的案例,并且根据意图选择了“公共”或“私人”。即使在团队中工作时,我仍然没有找到一个案例(根据我迄今为止的知识)为什么类变量和方法需要“受保护”。

【问题讨论】:

我真的很喜欢您的问题,并希望您在创建这样的新问题时可以通过某种方式 ping 我。你知道...特定于 PHP 5 的元编程问题。我知道你可以“ping”我的一种方法是在这里留下评论(它会出现在我的收件箱中)。我很乐意为您提供帮助,这可以帮助我分析为什么我会做一些事情,这也有助于我成为更好的程序员 我添加了一个赏金,因此这将“脱颖而出”成为人们思考的重要问题。 【参考方案1】:

使用protected,类或任何子类的对象都可以访问该属性。所以它很有用,如果你想要这个限制。

这不是绝对必要的,您也可以将每个属性设置为public,但是您将失去所有控制权,谁访问和/或更改它。其他人也可能会感到困惑,所有这些“公共属性”有什么用,他们可以访问。

另一方面,您可以使每个属性private,但每个子类也不能再访问它了。

【讨论】:

【参考方案2】:

我的理解是私有方法和属性不能被扩展的类看到;而受保护的方法和属性可以看到,但只能由定义它的类使用。

http://php.net/manual/en/language.oop5.visibility.php

【讨论】:

【参考方案3】:

例如,Flourish library 的 fDate 类提供了很多功能,但不是我需要的一切。所以我扩展了我自己的课程。

我很快发现它的核心内部变量 fDate::$date(自 1970 年以来的秒数)是一个私有属性。这使我不可能在我的子类 ThriveDate 中访问它。一旦 Flourish 的维护者将其更改为 protected 属性,我就可以使用它,从而充分扩展 fDate。

由于您永远不知道谁可能需要扩展您的类以及扩展多少,因此最好始终保护每个内部属性,除非有充分的理由让该属性永远不会被子类

TL;DR:私有属性应该和公共属性一样少见:例如几乎从不使用。

【讨论】:

谢谢。这就是我需要听到的令人信服的理由! :) 我愿意。封装:一句话:封装的意思是“不要问;告诉!”如果您曾经必须查询对象的状态以确定是否对该对象执行某项操作,那么您的对象封装得很差。一个封装良好的类通常有 0 个公共属性,0 个 setter,每 5 个非公共属性可能有 1 或 2 个 getter。如需更多信息,请联系我。 我不同意。很长一段时间以来,我习惯性地保护非公共成员,基于“好吧,也许有一天我会需要它”。对我来说,尽可能改变它并使用私有成员的关键原因是:一个受保护的成员被暴露,是你的对象联系的一部分。如果你曾经改变它的工作方式,你可能会下沉下游代码。因此,使用私有成员更易于维护。仅当您确实需要时才使用 protected。 -1 我不太赞成,但受保护的变量可能与公共变量一样危险。除非您有特定的理由不这样做,否则您应该将变量设为私有。 我也觉得“除非有充分的理由让该属性永远不会被子类修改”是一个糟糕的决定。类应该对扩展开放,对修改关闭【参考方案4】:

在设计类的时候,私有和公有不是很正常吗 变量或属性。

虽然我的 OOP 经验非常有限,但我 访问 CA-Visual Objects、Clipper、VB 和 ASP 中的 OOP 开发。

但是拥有一系列可以访问的公共属性是正常的 直接,然后是只能由类本身访问的属性。

当然,在 VB 和 ASP 中,这些是用 Get、Let 和 Set 方法定义的, 但您仍然可以直接访问它们。

您也可以设计只读属性。 也许这是因为运算符重载...

【讨论】:

你应该得到这本书,重构。这是一本很难读的书,而且有点无聊,但它解释了我认为我在这篇文章中从 Theodore R. Smith 那里读到的一些内容。这应该可以解释您在答案下发布的问题。【参考方案5】:

我主要出于测试目的使用受保护的方法和属性而不是私有的。这样在编写单元测试时创建类模拟就容易多了。

【讨论】:

【参考方案6】:

OOP 不会以将代码组织为类而告终(因为结构化编程不会以将代码拆分为函数而告终)。 PHP是一种脚本语言,所以当它作为OOP语言使用时,我们应该为自己设置约束。

我很幸运,第一次接触 OOP 时,语言是 Java,书是 Bruce Ekcel - Thinking in Java(你可以在亚马逊或其他商店购买,以前的版本也可以从这里免费下载:http://www.mindviewinc.com/Books/downloads.html)。我可以推荐这本书,即使对于 PHP 程序员也是如此。如果您不是完全的初学者,您将了解所有内容,并将其应用于 PHP。我正在尝试用 PHP 编程,就像它是 Java 一样(至少,OOP 部分;Java 中没有像 PHP 那样酷的关联数组)。

此外,私有、受保护和公共类别都不太精确。 public 应该分为“API 方法”和“可以从其他类调用”(参见“友好”),protected 应该区分“应该被覆盖”和“必须实现”。

学习 OOP,值得。

我还要说一件事,OOP 的基本模式:使用 getter/setter,不要使用公共属性,如果你使用公共属性,你只是将它刻骨铭心。比如说,有一个状态标志,现在它有 2 个可能的状态值,但是如果你想扩展它,必须修改所有代码,使用它。使用 setState() 和 getState(),它们的函数首先很简单($this->state = $param;return $this->state),但是会有扩展状态的含义没有问题,那么你应该只重写这些方法,即使在这种情况下,如果状态是一个派生值(例如它的值是从更多的标志计算出来的)。

在 OOP 中有几个或多或少相似的主题,这个 getter/setter 可能是最重要的基本主题。

所以,我的建议是:

使用 OOP,它是你的朋友; 像使用 JAVA(一种严格的 OOP 语言)一样使用 PHP,而不像在 FORTRAN 中那样使用。

【讨论】:

【参考方案7】:

现实生活中的例子怎么样:

<?
// burguers.php

/* abstract */ class BurguerClass 
  // nobody knows about these secret function
  private function addSecretRecipeSauce()  ...   

  // these one can can change in subclasses
  // cannot be called globally
  protected /* virtual */ function addBread()  ...   
  protected /* virtual */ function addSalad()  ...   
  protected /* virtual */ function addMeat()  ... 
  protected /* virtual */ function addExtraIngredients()  ... 

  // these one it can be access globally
  public /* virtual */ function makeBurguer() 
    $this->addBread();
    $this->addSalad();
    $this->addMeat();
    $this->addExtraIngredients();
    $this->addSecretRecipeSauce();
    


/* concrete */ class CheeseBurguerClass extends BurguerClass 
  protected /* virtual */ function addCheese()  ... 

  public /* override */ function makeBurguer() 
    $this->addBread();
    $this->addSalad();
    $this->addMeat();
    $this->addExtraIngredients();
    // we add this one:
    $this->addCheese();
   


/* concrete */ class RanchStyleBurguerClass extends BurguerClass 
  protected /* override */ function addExtraIngredients()  ... 


/* concrete */ class EastCoastVegetarianStyleBurguerClass extends BurguerClass 
  protected /* override */ function addMeat() 
    // use soy "meat"
  
  protected /* override */ function addExtraIngredients()  ... 


function burguers_main() 
    $Cheesburguer = new CheeseBurguerClass();

    // can be access
    $Cheesburguer->makeBurguer();


// execute it
burguers_main();

?>

您只需打开“Can I have a Cheesburguer”软件开发公司即可。你是C.E.O.,你有几个下属。你教下属他们可以根据“burguerClass”食谱制作新产品,并制作新食谱。

你告诉你的员工如何“addBread”、“addSalad”、“addMeat”、“addExtraIngredients”,并且操作可以被新的改变,但不能单独出售,只能在“makeBurguer”操作中使用.

但是,你不教你的员工“addSecretRecipe”操作。

【讨论】:

以上是关于PHP5 保护变量背后的推理的主要内容,如果未能解决你的问题,请参考以下文章

概率图模型(推理:变量消除)

概率图模型(推理:变量消除)

PHP5中Static和Const关键字

Lisp DO 变量语法推理

php5.5过渡--变量

PHP 打开PHP5对象,无需先声明变量名