类型声明

简介:

在PHP7之前,我们在函数和类之间传递参数时不必声明变量类型,返回数据时也不必声明变量类型。任何数据类型都可以被传递、返回。这样会给PHP带来一个很大的问题:PHP不清楚传递的是什么类型的变量,函数、方法接收到的变量也不知道是什么类型。为了解决这个问题,PHP7中引入了类型声明,目前明确的有两类变量可以声明类型:形参和返回值。

类型声明在OOP与PHP程序中属于同一个特性,因为它既可以用在程序的函数中,也可以用在对象的方法中。

形参类型声明:

PHP7支持的形参类型声明的类型有:字符串型(string), 整型 (int), 浮点类型 (float), 以及布尔类型 (bool)。

class Person
{
    public function age(int $age)
    {
        return $age;
    }

    public function name(string $name)
    {
        return $name;
    }

    public function isAlive(bool $alive)
    {
        return $alive;
    }
}


$person = new Person();

echo $person->name('Revin');
echo $person->age(27);
echo $person->isAlive(TRUE);

上面的代码,创建一个 Person 类,里面有三个方法,每个方法接受不同类型的形参且有着类型声明。如果执行上面的代码,能够正确运行并通过类型检测。

Age 支持浮点数型,例如 27.5 如果传递一个浮点数作为age方法的形参,也是正常运行的。代码如下:

echo $person->age(30.5);

默认请看下,形参类型声明不是完全限制的,这就意味着我们可以传递一个浮点给期望得到整型数的方法, 也同样可以传递一个整形给期望得到整形术的方法。

//echo $person->name(11111111111);
echo $person->name('Revin');
echo $person->age(27.5);
echo $person->isAlive(TRUE);

这样也就失去了指定声明形参类型,不过可以做一些限制,代码如下:

开启严格模式. 注意必须放在程序首行,否则会报Fatal error: strict_types declaration must be the very first statement in the script in ...

declare(strict_types = 1);

此时我们若再传递一个浮点数给age方法的话,会得到一个 Fatal error: Uncaught TypeError,这个Fatal 错误 的意思是 Person::age 只能接受一个整型数而非浮点型数。

注意:爱需要字符串形参的情况下,如果传入的不是字符串形参的话,也会出现以上类似的Fatal 错误。例如以下报错代码:

echo $person->isAlive('true');

返回类型声明:

PHP 7 的另一个重要特性就是支持返回类型的声明,无论实在函数还是对象的方法中。

这有点类似形参类型声明,对刚才的 Person 类进行修改,代码如下:

declare(strict_types = 1);

class Person
{
    public function age(float $age) : float
    {
        return $age;
    }

    public function name(string $name) : string
    {
        return $name;
    }

    public function isAlive(bool $alive) : string
    {
        return ($alive) ? 'Yes' : 'No';
    }
}

$person = new Person();

echo $person->name('revin');
echo $person->age(27.5);
echo $person->isAlive(TRUE);

上面的代码 返回类型声明使用了 data-type 语法,对于形参类型声明与返回类型声明。

举个返回类型是对象的栗子:

修改上面的代码,加Address类, Person 类中加入 getAddress 方法,并且返回类型是Address对象。

declare(strict_types = 1);

class Address
{
    public function getAddress()
    {
        return ['street' => 'shanghai', 'country' => 'China'];
    }
}

class Person
{
    public function age(float $age) : float
    {
        return $age;
    }

    public function name(string $name) : string
    {
        return $name;
    }

    public function isAlive(bool $alive) : string
    {
        return ($alive) ? 'Yes' : 'No';
    }

    public function getAddress() : Address
    {
        return new Address();
    }
}

$person = new Person();

var_dump($person->getAddress());

上面的代码执行没有问题,调用Persion 类中的 getAddress 方法执行完毕后,返回一个Address类型的数据。

若上面Persion 类中的getAddress 方法修改如下

    public function getAddress() : Address
    {
        return ['street' => 'shanghai', 'country' => 'China'];
    }

再次实行会Fatal 错误,这是因为Persion 类中的 getAddress 方法返回了一个数组,而不是方法声明的Address类型的返回值。

Fatal error: Uncaught TypeError: Return value of Person::getAddress() must be an instance of Address, array returned in ..

为什么要使用类型声明?

它可以让函数、方法的形参与返回值有所预期,避免出现不必要的数据传递,从而造成错误。PHP 7 这个特性使代码更清晰且可读性更强,能够清楚的知道怎么样的数据类型将会被传递与返回。

补充知识: 三个点语法是什么?

当你看php7 官方的相关文档时m会看到... 的东西,如下示例:

<?php
// Coercive mode
function sumOfInts(int ...$ints)
{
    return array_sum($ints);
}

var_dump(sumOfInts(2, '3', 4.1));

其实这是PHP5.6 新特性-PHP 可变参数,详情官方文档:http://php.net/manual/zh/functions.arguments.php#functions.variable-arg-list , 把传进来的值,转成数组.

资料:

PHP 7 标量类型声明 RFC

Last updated