我系统中的几个资源使用基于Java集合的对象集合的概念。
此Collection Class(abstract)为另一个具体类提供了基本功能,称为Lists,它允许通过Collection的索引查找对象。
我将使用我的HTTP Headers类作为示例进行解释。
我在其构造函数中有一个这个Lists类的实例。每个HTTP标头字段都通过 Headers :: addHeader()方法添加到集合中。
显然,我有一个名为 getHeaders()的 getter 方法,它返回Collection的存储,而不是Collection的对象< /强>
因此,如果我需要在此课程之外列出标题,我只需要调用 $ obj - &gt; getHeaders(),我有一个添加了所有对象的ArrayObject。
好的!
但是,最近,出现了使用Lists方法之一 Lists :: find()的必要性,它找到一个对象,甚至不知道对象的名称或其在Collection的存储中的具体位置。 / p>
由于Lists对象位于私有属性中,因此Headers :: getHeaders()返回Collection Storage,我不想违反封装,通过使属性成为公共属性,我无法访问此方法。 / p>
除了功能之外,我编写的所有内容都必须在视觉上优雅,并创建另一个getter方法,假设getHeadersLists()会产生如下调用:
$obj -> getHeadersLists() -> find( 'foo' );
这太丑了!
所以,我在Headers Class中快速添加了一个__call(),它运行良好:
$obj -> find( 'foo' );
但我认识的人(他非常精通面向对象主题)告诉我这是错误的。
我的论点纯粹是关注可读性,他反驳说“在面向对象,魔术方法和可读性方面不能共存”。
那又怎样?我应该怎么做才能在这两个类之间创建这个“桥梁”,而不使用_call()并保留Object Orientation的原则?
我知道,我可以在Headers :: getHeaders()中返回Collection对象并使用类似的东西:
$obj -> getHeaders() -> find();
但我学到的关于面向对象的东西是责任。正如其声明所说,这种方法的责任在于返回所有添加的Headers,而不是外部对象。
答案 0 :(得分:1)
我打算用鲍勃叔叔的单一责任原则a.k.a(S.O.L.I.D的大S)打你。您可以在Principles Of OOD文章中阅读更多内容。也可以直接回答您的问题Tom Dalling's very nice article and example。
隐藏getHeaders()函数调用时出现的问题,返回类型为 Lists 的对象,然后看起来你正在调用该对象,并且它有一个名为find的函数“它不应该有”因为找到正确的标题不是他的责任。
我能理解你的责任方法。
你说:当我调用getHeaders()时,我不应该被迫进一步操纵结果以获得我想要的结果。
你的这个建议完全正确。但是要实现这个结果,隐藏带有合成糖的getHeaders()函数调用完全错误。因为它会误导我。
考虑到我作为第三方阅读您的代码,我会立即假设该类的find()函数非常具有误导性。此外,我会拒绝这个find()函数,因为从标题列表中查找不是来自对象的责任,这只是一个不必要的附加组件或错误。所以你的同事也是正确的:D。
我认为迫使你调用 find()以便能够使用标题类型对象的情况应该归咎于此。
我对你的困境的建议是这样的。
现在我的朋友只剩下一个小小的消息了。我相信你的讨论会引发一个更有趣的问题,你和你的队友应该问这个问题。
几乎总是,如果你需要获得一个对象的某些属性并对它们采取行动。然后,您还应该能够将该功能封装到该对象/类中。当你获得一个对象属性并使用它来做某事然后把它放回去时,几乎总是代码味道。
为什么这个对象没有尽职尽责,但你是 为他操纵他的财产?
感谢您的时间,我希望我能帮助您:D。
答案 1 :(得分:0)
这就是为什么在PHP中有一个“受保护”的范围,就像其他O.O.编程语言。
如果您知道,后代类可以访问“受保护”成员,但不能将其作为公共访问。
作为一个建议,我通常不会使用“私人”,而是“受保护”,原因与您的帖子相同。