在PHP中什么时候应该使用类型提示?

25

我不理解PHP作者添加类型提示的动机。在它出现之前,我很开心地过着生活。然而,自从它被添加到PHP 5中,我开始到处指定类型。现在我认为这是一个坏主意,因为鸭子类型确保类之间最小耦合,并促进代码模块化和重用。

感觉类型提示将语言分成了两个方言:有些人以静态语言的方式使用提示编写代码,而其他人则坚持使用老式的动态语言模型。或者这不是“全部或无”的情况吗?在适当的时候,我是否应该以某种方式混合这两种风格?

6个回答

37

这并不是关于静态类型和动态类型的问题,PHP 仍然是动态类型语言。重要的是为接口制定合同。如果您知道一个函数需要一个数组作为其参数之一,则在函数定义中直接强制它。我更喜欢快速失败,而不是在函数后期出现错误。

(还要注意,在动态上下文中不能指定 bool、int、string、float 的类型提示是有道理的。)


3
没错,我同意。我只是觉得,所有那些严格的合约对于最初的鸭子类型语言来说有点陌生。PHP已经够丑了,而类型提示使它看起来更像一个没有关联特性的堆积。 - Ivan Krechetov
4
我不知道,PHP正在发展(OOP)。对于复杂数据类型来说,严格的接口对我很有意义。 - Mario
2
此外,您可以获得最佳的两个世界,定义严格性在必要时进行,或者不进行,并将小事情保持动态。 - Mario
3
最终会有一个时间点,你需要检查所接收到的内容是否真正符合你期望的类型。类型提示可以在函数定义中直接实现这一目的。 - Ikke

17

当函数的代码明确依赖于传递参数的类型时,应该使用类型提示。无论如何,代码都会生成错误,但类型提示将为您提供更好的错误消息。


1
我的PHP代码仅依赖于针对传递的参数对象调用的方法的存在。为什么要限制自己要求特定类型呢? - Ivan Krechetov
5
在这种情况下,为您的对象创建一个接口并实现它,并使用该接口名称对您的函数进行类型提示。这是一个可靠的约定。 - Mario
1
真的。总是(也许除了一些特殊情况)对接口进行类型提示 - 而不是具体类。 - troelskn

13
PHP团队引入类型提示的动机是为了向习惯Java风格面向对象编程的人提供更多功能,使平台更加熟悉、舒适和吸引人。这反过来将使PHP更具“企业就绪性”,这将有助于Zend的核心业务。
撇开营销不谈,它确实有其用处。如果您正在编写一个以特定方式操作参数的方法,并且如果参数是其他内容,则会导致意外(通常是静默)的失败,那么使用类型提示可以确保代码在开发期间中断,而不是在生产期间中断。

6

如果您决定使用类型提示,至少请使用接口而不是具体或抽象类。原因很简单,PHP不允许多重继承,但允许实现多个接口。因此,如果任何人尝试使用您的库,他将不会在实现您的接口时遇到困难,而不是在他已经继承另一个类的情况下必须扩展您的抽象/具体类的情况。


0
没有类型提示,IDE 将无法知道方法参数的类型,因此无法提供正确的智能感知 - 你的编辑器有智能感知功能,对吧?;). 应该说,我只是假设 IDE 使用这个来进行智能感知,因为这是我第一次听说 PHP 中的类型提示(顺便感谢提示)。

2
有一个用于phpdoc注释的东西。 - Ivan Krechetov

-4

类型提示是我们公司的争议点(主要是Java人员喜欢它),而我是一个非常老派的PHP程序员(并在其他语言中编程)。

我的建议是避免使用类型提示,并在每个复杂函数中包含try/catch处理程序。

类型提示强制应用程序依赖于调用者的异常处理环境,这通常是不好的并且未经测试的主要问题。对于Web应用程序,这会导致白屏死机,对于批处理,则会导致简单的致命退出而没有记录大多数情况下的良好消息,您坐在那里挠头,试图重新创建用户或应用程序问题,管理层要求您解决问题。

本地异常处理提供了更受控制的测试场景,包括垃圾数据类型和垃圾数据值,与通过传递不正确的类型并期望异常的调用者中难以测试的异常处理路径相比,这提供了一个更完整的测试套件。

异常测试在许多情况下也会因为堆栈版本问题而失败(即某些 PHP 版本,如 5.4,无法以适当的方式捕获“可捕获致命”错误,因此 PHPUnit 简单地停止运行测试套件。这是一个特定于堆栈的问题,然而根据我的经验,类型提示根本是不必要的,它使习惯于有类型语言的人更好地接受 PHP 而不意识到影响,并导致更复杂的测试场景(非常难以测试调用者处理异常路径结果)。
Java 和其他有类型语言的人并不接受或理解如何利用和从 PHP 的默认混合类型参数中受益... 他们总有一天会学会,但只有当他们拥抱 PHP 的方式时才能做到。;-)
最好的教训是在开发强大的基于 PHP 单元测试场景时学到的,这通常会揭示为什么类型提示与测试相关是个麻烦,并且会引起更多问题而不是好处... 各取所需,我的应用程序运行得更好、更可靠,测试结果更完整,通常包括本地函数中的 catch 路径,覆盖了 100% 的代码。

如果你想在代码和生活中充斥着异常处理和琐碎冗余的单元测试,而这些测试可以被现成的集成开发环境和静态分析工具所取代,那就遵循这些建议吧。哦,还有一个遵循这些建议的动机是破坏你的代码的可读性、可维护性和重构性。 - obe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接