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 保护变量背后的推理的主要内容,如果未能解决你的问题,请参考以下文章