类型提示:方法应该接受任何作为对象的 $art

Posted

技术标签:

【中文标题】类型提示:方法应该接受任何作为对象的 $art【英文标题】:typehinting: method should accept any $arg that is an object 【发布时间】:2011-05-12 05:55:42 【问题描述】:

我有一个类 'Collection',它有一个 add 方法。 add 方法应该只接受对象。所以这是期望的行为:

$x=5;//arbitrary non-object
$obj=new Foo; //arbitrary object

$collection=new Collection;
$collection->add($obj); //should be acceptable arg, no matter the actual class
$collection->add($x); //should throw an error because $x is not an object

根据 php 手册,可以通过在 $arg 前面加上类名来输入提示方法。由于所有 PHP 类都是 stdClass 的子类,我认为这个方法签名会起作用:

public function add(stdClass $obj);

但它失败并显示“参数必须是 stdClass 的实例”。

如果我将签名更改为我定义的父类,那么它可以工作:

class Collection 
  public function add(Base $obj)
    //do stuff
  


$collection->add($foo); //$foo is class Foo which is an extension of Base

有人知道如何为通用对象键入提示吗?

【问题讨论】:

assert(is_object($arg)); 就是你所需要的。 【参考方案1】:

PHP 中没有根类。对象甚至不继承自stdClass

class Foo 
var_dump(new Foo instanceof stdClass); // bool(false)
var_dump(get_parent_class(new Foo));   // bool(false)

显然,PHP 中没有已知的方法可以为 object 键入提示,即使 object 是 PHP 中的一种数据类型(如 array),并且类型转换为 object 会产生一个 stdClass 对象:

echo get_class((object) "string"); // stdClass

我想作为一种解决方法,如果is_object($obj) 返回 false,您可以告诉该方法抛出异常或死于致命错误。

【讨论】:

我想既然你可以实例化stdClass,它必须是所有对象的基类。每天学些新东西。我想知道为什么 PHP 决定这样做。【参考方案2】:

问题是,PHP 仍然是一种动态语言,类型提示就是:提示。我认为您将不得不退回到旧的 is_object 或类似方法并抛出自定义异常。

class Collection 
  public function add(Base $obj)
    if(!is_object($obj))
    throw new Exception("Parameter must be an object");
    // do stuff
  

【讨论】:

【参考方案3】:

与 Java 的 Object 类不同,PHP 没有对象的基类。对象不继承stdClass:它是默认的对象实现,而不是基类。因此,不幸的是,您不能为 PHP 中的所有对象键入提示。您必须执行以下操作:

class MyClass 
    public function myFunc($object) 
        if (!is_object($object))
             throw new InvalidArgumentException(__CLASS__.'::'.__METHOD__.' expects parameter 1 to be object");
    

幸运的是,PHP 已经为此目的定义了 InvalidArgumentException 类。

【讨论】:

+1 表示InvalidArgumentException。请注意,它仅在加载 SPL 时可用。 你也可以在你的异常字符串中写__METHOD__而不是MyClass::myFunc 是的。幸运的是,SPL 从 5.0.0 开始默认加载。我不明白为什么有人会禁用它,它非常有用。【参考方案4】:

在 PHP 7.2 中现在有一个 object 类型提示。你可以简单地做

class Collection 
  public function add(object $obj)
    //do stuff
  
 

【讨论】:

以上是关于类型提示:方法应该接受任何作为对象的 $art的主要内容,如果未能解决你的问题,请参考以下文章

PHPDoc 或类型提示类作为方法的参数

如何更新 json 类型的 json 中的任何字段?它应该接受一个对象或一个键数组,如果它存在则更新键,否则创建

为啥类型 `Record<string,unknown>` 不接受具有已定义键的对象作为值

面向对象2

我需要一个接受任何类型对象的数组或 ArrayList

Type 应该采用啥协议来让泛型函数将任何数字类型作为 Swift 中的参数?