3

众所周知,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
{
}



?>

我希望 ConcreteClass 实例以及所有未来未知的用户定义对象也能被 SetObject 接受。您如何在检查正确类型时允许这样做?

4

7 回答 7

11

实际上,对于类,您可以在 PHP (5+) 中提供类型提示。

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

正如您所期望的那样,这也将与继承一起正常工作。

顺便说一句,不要在你的类名中加上“对象”这个词......

于 2008-09-26T02:00:01.077 回答
4

作为对 Eran Galperin 响应的补充,您还可以使用类型提示来强制参数为数组 - 而不仅仅是某个类的对象。

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

如您所见,您可以键入该::passMeAnArray()方法需要的提示,array并提供一个默认值,以防在没有任何参数的情况下调用该方法。

于 2008-09-26T02:05:43.743 回答
2

对于原始类型,您还可以使用 is_* 函数:

public function Add($a, $b)
{
  if (!is_int($a) || !is_int($b))
    throw new InvalidArgumentException();
  return $a + $b;
}
于 2008-10-04T12:16:50.353 回答
1

@Eran Galperin的回复是确保您使用的对象类型正确的首选方法。

另外值得注意的是instanceOf运算符 - 当您想要检查对象是否是多种类型之一时,它很有帮助。

于 2008-09-26T02:28:47.510 回答
1

你看,关于类型提示有多个答案。这是技术解决方案。但是你也应该确保整个设计是明智和直观的。这将使类型问题和错误更加罕见。

请记住,即使是这些类型的错误也会在运行时抛出。确保您对代码进行了测试。

于 2008-09-26T07:08:24.203 回答
1

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

无论如何,我认为总是试图防止长大的程序员将错误的对象传递给方法并不是一个好的时间投资:你可以把它花在文档和培训上。

你需要的是鸭式打字和细心的同事,而不是让你的应用程序更加僵化的额外检查。

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

于 2008-09-27T11:48:55.727 回答
0

您可以在 php.ini 文件中设置 error_reporting ini 设置或使用 error_reporting 函数在运行时设置它

于 2008-09-26T03:19:28.437 回答