使用类型提示时无法传递null参数

Abd*_*lah 166 php type-hinting

以下代码:

<?php

    class Type {

    }

    function foo(Type $t) {

    }

    foo(null);

?>
Run Code Online (Sandbox Code Playgroud)

在运行时失败:

PHP Fatal error:  Argument 1 passed to foo() must not be null
Run Code Online (Sandbox Code Playgroud)

为什么不允许像其他语言一样传递null?

Don*_*sto 311

你必须添加一个默认值

function foo(?Type $t) {
}
Run Code Online (Sandbox Code Playgroud)

这样,您可以传递一个空值.

有关类型声明的手册部分中对此进行了说明:

null如果参数的默认值设置为,则可以使声明接受值Type $t = null.

从PHP 7.1(2016年12月2日发布)开始,您可以null使用此语法显式声明变量

$this->foo(new Type()); // ok
$this->foo(null); // ok
$this->foo(); // error
Run Code Online (Sandbox Code Playgroud)

这将导致

function foo(Type $t = null) {

}
Run Code Online (Sandbox Code Playgroud)

因此,如果你想要一个可选参数,你可以遵循约定,NULL而如果你需要让一个参数接受它们NULL和它的类型,你可以按照上面的例子.

你可以在这里阅读更多.

  • 在我看来,这是一种糟糕的语言结构.1.在其他语言中,null具有任何类型的能力,因此在这种情况下使null成为有效参数.2:Php使用参数的默认值来指定null是允许的,这是不明确的,即使开发人员想要强制显式传递null,它也使得必需参数不可用. (22认同)
  • 那么为什么不是null null对象*? (10认同)
  • 我同意@Henry仅在2.关于1,你不能将null传递给`function foo(Type $ t)`是一件非常好的事情; 见[Null References:The Billion Dollar Mistake](https://en.wikipedia.org/wiki/Nullable_type#cite_note-4) (6认同)
  • 大多数语言允许null具有任何类型.在这种情况下. (4认同)
  • 我同意@Henry,另外在看起来像一个可选的参数之后需要params看起来很奇怪. (2认同)

The*_*tor 32

从PHP 7.1开始,可以使用可空类型作为函数返回类型和参数.类型?T可以具有指定Type的值T,或null.

所以,你的功能可能如下所示:

function foo(?Type $t)
{

}
Run Code Online (Sandbox Code Playgroud)

只要你可以使用PHP 7.1,这个表示法应该是首选function foo(Type $t = null),因为它仍然强制调用者显式指定参数的参数$t.


Sea*_*nWM 12

尝试:

function foo(Type $t = null) {

}
Run Code Online (Sandbox Code Playgroud)

查看PHP函数参数.

  • 我遇到的问题是它改变了函数的定义.现在参数是可选的 - 这实际上并不是作者的意图(尽管,如果他传递的是null,则它是隐式可选的). (11认同)

Sys*_*all 12

从 PHP 8.0(2020 年 11 月 26 日发布)开始,您还可以使用可空联合类型

这意味着您可以传递Typenull作为参数值:

class Type {}
function foo(Type|null $param) {
    var_dump($param);
}

foo(new Type()); // ok : object(Type)#1
foo(null);       // ok : NULL
Run Code Online (Sandbox Code Playgroud)

阅读有关联合类型的更多信息。


Fab*_*ler 5

正如已经提到的其他答案一样,只有将其指定null为默认值,才有可能。

但是最干净的面向类型安全的面向对象的解决方案将是NullObject

interface FooInterface
{
    function bar();
}
class Foo implements FooInterface
{
    public function bar()
    {
        return 'i am an object';
    }
}
class NullFoo implements FooInterface
{
    public function bar()
    {
        return 'i am null (but you still can use my interface)';
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

function bar_my_foo(FooInterface $foo)
{
    if ($foo instanceof NullFoo) {
        // special handling of null values may go here
    }
    echo $foo->bar();
}

bar_my_foo(new NullFoo);
Run Code Online (Sandbox Code Playgroud)

  • 这种方法通常是不切实际的,因为您现在需要 3 个类,而不是 1 个类。此外,它迫使 `NullFoo` 的编写者重写抽象方法,即使它们没有任何意义(根据 `null` 的定义)。 (2认同)