如何防止在PHP中使用错误的类型?

时间:2020-03-06 14:45:40  来源:igfitidea点击:

众所周知,PHP是非常宽松的类型。该语言不需要我们为函数参数或者类变量指定任何类型。这可能是一个强大的功能。

但是有时,它可能使调试脚本成为一种痛苦的体验。例如,将一种对象传递给期望使用另一种对象的方法可能会产生错误消息,说明传递的对象不存在某种变量/方法。这些情况主要是烦人的事情。更麻烦的问题是当我们使用错误类的对象初始化一个对象时,直到脚本执行的稍后阶段,才会使用"错误对象"。在这种情况下,与传递原始参数相比,最终会出现错误得多的错误。

与其抱怨我传递的内容没有特定的方法或者变量,或者不等到脚本执行之后很长时间才等待我传递的对象被使用,我宁愿在我确切指定对象的位置上看到一条错误消息类型错误,抱怨对象的类型不正确或者不兼容。

我们如何在代码中处理这些情况?如何检测不兼容的类型?如何在脚本中引入一些类型检查,以便获得更容易理解的错误消息?

另外,如何在考虑Php的继承的同时执行所有这些操作?考虑:

<?php
class InterfaceClass
{
#...
}

class UsesInterfaceClass
{
   function SetObject(&$obj) 
   {
       // What do I put here to make sure that $obj either
       // is of type InterfaceObject or inherits from it       

   }
}
?>

然后,此代码的用户使用其自己的具体类来实现该接口:

<?php

class ConcreteClass extends InterfaceClass
{
}

?>

我希望ConcreteObject实例以及所有将来的,未知的用户定义对象也可以被SetObject接受。在检查正确的类型时,我们将如何允许它?

解决方案

实际上,我们可以为类提供PHP(5+)中的类型提示。

<?php
 class UsesBaseClass
 {
      function SetObject(InterfaceObject $obj) 
      {
      }
 }
 ?>

这也可以像我们期望的那样正确地与继承一起使用。

顺便说一句,不要在类名中添加"对象"一词。

除了Eran Galperin的响应之外,我们还可以使用类型提示来强制将参数设置为数组,而不仅仅是特定类的对象。

<?php
class MyCoolClass {
   public function passMeAnArray(array $array = array()) {
      // do something with the array  
   }  
 }  
 ?>

如我们所见,我们可以输入提示::: passMeAnArray()方法需要一个array并提供默认值,以防该方法不带任何参数。

@Eran Galperin的响应是确保所使用的对象类型正确的首选方法。

另外值得注意的是instanceOf运算符,它在我们要检查对象是否为多种类型之一时非常有用。

我们可以在php.ini文件中设置error_reporting ini设置,或者使用error_reporting函数在运行时进行设置

我们会看到关于类型提示的多个答案。这是技术解决方案。但是,我们还应该确保整个设计合理且直观。这将使类型问题和错误更加少见。

请记住,即使这些类型失败也会在运行时引发。确保对代码进行了测试。

即使在我们描述的情况下,脚本也会崩溃,并抱怨对象Y上没有方法/属性X,因此我们将知道这是从哪里来的。

无论如何,我认为始终试图阻止长大的程序员将错误的对象传递给方法并不是一个好时机投资:我们可以将其用于记录和培训。

我们只需要鸭子打字和细心的同事,而无需进行其他检查,否则会使应用程序更加僵化。

但这可能是Pythonista的观点...

对于基本类型,我们还可以使用is_ *函数:

public function Add($a, $b)
{
  if (!is_int($a) || !is_int($b))
    throw new InvalidArgumentException();
  return $a + $b;
}