从面向对象的 PHP 开始使用类作为方法的集合是否明智?这种方法有什么缺点吗?
我知道 OOP 远不止这些,但我的 PHP 项目太小,无法利用 OOP 提供的所有功能。另一方面,我的项目变得太大而无法仅通过程序编程来更新/维护。
我读过很多关于 OOP 的主题,偶尔有人说“OOP 不仅仅是函数的集合”(或类似的东西)。这让我想到:这可能是真的,但这也可能是我通过这样做最终潜入 OO 编程世界的机会。
那么,这是真正开始使用和学习 OOP 的明智的第一步吗?还是我需要了解一些严重的缺点?
您的问题确实很宽泛,但是当您继续进入面向对象分析和设计 (OOAD) 的世界时,它应该得到一个简单的答案,您可以记住并随身携带。
那么,这是真正开始使用和学习 OOP 的明智的第一步吗?还是我需要了解一些严重的缺点?
可以想象,我们不可能直接回答这个问题。什么聪明,什么不聪明,很大程度上取决于我们自己的能力。例如,对于某些人来说,它可能很聪明,因为它可以帮助他们及早停止错误,这是要走的路。对于其他人来说,这可能是一场彻底的灾难,因为他们没有发现任何错误,继续开发软件,因为他们认为:如果我没有发现错误,这是完全正确的。
那么如何解决这个困境呢?很简单,我们在 OOP 中有两个部分,您可以轻松了解并随身携带。第一个被称为STUPID - 你可以想象如果某物属于这一类意味着什么,第二个被称为SOLID,它同样是自言自语如何对待其中的东西。
免责声明:我有一段时间没有处理 php,所以我的语法可能是错误的。
OOP 这个词在 imo 中有点模糊,意思是不同的人听到它时会想到略有不同的东西,所以当你听到关于它的矛盾的东西时不要感到困惑。
使用类将类似的函数构造在一起不会损害您的代码,但是您基本上只是将类用作函数的命名空间。通常,您会希望以封装系统某些方面的方式定义类,这意味着只有该类的代码必须直接处理该方面,而其他人只使用该类。
例如,您可以有一个管理打印作业队列的类。如果您有一些想要打印文档的代码,它不必知道作业如何排队或在哪里排队或如何将它们发送到打印机,它只需要知道打印作业队列对象(我们称之为$jobQueue
) ,它可能有一个类似的方法$jobQueue->enqueue($document)
。
现在您可能会争辩说:“该代码也可以使用全局函数enqueueJob($document)
”,直到您想要拥有多个队列(用于不同的打印机)以及以不同方式工作的队列(将作业存储在数据库中)之前,这是正确的,在内存中,或者根本没有 - 想象一个队列直接进入回收站:))。使用 OOP,这种情况是没有问题的,并且这些细节对想要打印文档的代码完全隐藏 - 它所关心的只是它有一个带有enqueue
方法的作业队列对象。
为了获得作业队列的这种“可互换性”,他们需要有一个公共接口(在这种情况下,enqueue
方法),必须仔细选择它来满足想要打印东西的代码的所有需求,但不关于打印队列如何工作的太多假设。例如,您可以想象该enqueue
方法将文件路径作为参数,该参数告诉队列将其文件存储在哪里 - 但该接口对于在数据库上工作的队列来说是无用的。这是找到好的抽象的艺术。
现在回到你原来的问题,在我看来,仅仅将相关的函数打包到一个类中并不是真正的 OOP,只要不考虑新类应该提供哪些抽象/接口。没有它,使用这个新类的所有代码都将被硬连线以使用它,并且如果您决定需要不同类型的打印机队列,则需要更改/重新检查。:)
但是,“不是 OOP”与“不是一个好主意”不同。我说去吧,重新安排你的职能。在我看来,重要的是要记住,并非所有事物都需要成为对象或适合某种抽象。但也许你会发现你确实有一些函数可以做类似的事情(文件中的队列,数据库中的队列),这些函数可以抽象为一个通用接口。
OOP 基本上只是一组方法。但是编程中的思维是不同的。在类中,您封装了类似的功能。代码更具可读性,您不需要一遍又一遍地编写相同的功能。它也更安全(私人成员),如果您正在编写库,最终用户只能更改您想要的内容等。所以我不建议尝试使用一组函数绕过 OOP 并改用真正的 OOP。没有理由不这样做。
我不推荐,你会习惯于编写掩码为 OOP 的过程代码,这并不是你真正想要的。一开始可能很难,但是学习 OOP 的所有特性,阅读模式,强调编码标准,最重要的是,学习面向对象架构的应用程序。
由于这个问题实际上与 php 无关,而是与一般的 OOP 相关,因此这个答案应该对许多语言都有效。
OOP 中存在不同的模式。我建议阅读“四人帮”。这是一本非常好的书,它解释了一些在做 OOP 时可以使用的最基本的模式。
与其使用类来保存一组静态函数,不如考虑将所有函数存储在命名空间中。
类通常定义对象(如物理对象)。任何物理对象都有一组属性和行为。
在设计一个类时,您试图定义这些行为和属性。例如,一个包。
class Bag:
// Methods
function open: ...
function close: ...
function empty: ...
function add(item): ...
// Properties
array items: []
bool is_open: false
某些属性或方法可以对世界隐藏或可见。在我的示例中,每当您尝试清空或将对象添加到封闭的袋子时,您都可以让函数 add 抛出异常。很明显,这里的所有方法都与实际对象相关。
添加与包无关的方法或属性应该属于不同的命名空间或类。这真的取决于你想要做什么。
有些东西是功能性的、程序性的并且基于一个对象。使用最适合情况的一种。你不会对这种哲学大错特错。