# 类型声明

## 简介：

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

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

## 形参类型声明：

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

```php
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方法的形参，也是正常运行的。代码如下：

```php
echo $person->age(30.5);
```

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

```php
//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 ...`

```php
declare(strict_types = 1);
```

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

> 注意：爱需要字符串形参的情况下，如果传入的不是字符串形参的话，也会出现以上类似的Fatal 错误。例如以下报错代码：
>
> ```php
> echo $person->isAlive('true');
> ```

## 返回类型声明：

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

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

```php
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对象。

```php
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 方法修改如下

```php
    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
<?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](http://blog.jobbole.com/91735/)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://php7.shujuwajue.com/php-70x-xin-te-xing/oop-te-xing/lei-xing-sheng-ming.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
