PHP各版本中函数的类型声明详解

PHP7开始支持标量类型声明,强类型语言的味道比较浓。使用这个特性的过程中踩过两次坑:一次是声明boolean,最近是声明double。为避免以后继续犯类似错误,就把官方文档翻了一次。本文是看完后对PHP函数的类型声明使用做的一次总结。

从语法上,PHP的函数定义经过了几个时期:

远古时代(PHP 4)

定义一个函数非常的简单,使用 function name(args) {body} 的语法声明。不能指定参数和返回值类型,参数和返回值类型有无限种可能。这是到目前为止最常见的函数声明方式。

数组和引用类型参数值声明(PHP 5)

数组(array)、类(class)、接口(interface)、函数(callable)可以用在函数声明中。从5.6开始,支持常量(包括类常量)为默认参数,以及参数数组(以省略号…为前缀)。例如:

function sum(...$numbers) {
  $sum = 0;
  foreach ($numbers as $number) {
    $sum += $number;
  }
  return $sum;
}

注意:如果参数的值可能为null,null必须为参数的默认值,否则调用时会出错。例如:

function foo(array $arr = null) {
  ...
}

标量类型和返回值声明(PHP 7)

函数正式支持标量类型(int, bool, float等)和返回值类型(可声明类型同参数)声明。从这个版本开始,写PHP有像写java的感觉。

遗憾是如果函数返回值有可能是null,就不能指定返回值类型。例如:

function getModel() : Foo {
  if ($this->_model === null) {
     $this->_model = xxxx; // get from db or otherelse
  }
  return $this->_model;   // 如果$this->_model仍是null,运行出错
}

参数和返回值可为null以及void返回类型声明(PHP 7.1)

当参数和返回值类型有可能是null时,类型前以问号(?)修饰,可以解决null值问题(与默认参数不冲突);类型声明新增iterable,同时还支持void类型返回值。例如:

function getModel(?int $id) : ?Foo {
  if ($id !== null) {
    $this->_model = xxxx;
  } else {
    $this->_model = yyyy;
  }
  return $this->_model;
}

// 调用
$foo->getModel(null);
$foo->getModel(100);

// 函数声明了参数并且没有提供默认参数,调用时不传入参数会引发错误
// 将函数声明改成 getModel(?int $id = 100) {},可以不传参数
$foo->getModel();

当函数返回值为void时,函数体的return后不能接任何类型,或者不出现return语句。

function test(array $arr) : void {
  if (!count($arr) {
    return;
  }

  array_walk($arr, function ($elem) {xxxx});
}

回顾完以上历史,可以看出到PHP 7.1,函数类型声明已经十分完善(虽然实践中用的不多)。

再说说实践中踩到的坑。参数和返回值类型声明可用的类型有:

  1. 类/接口
  2. self,只能用在自身的方法上
  3. array
  4. bool
  5. callable
  6. int
  7. float
  8. string
  9. iterable

注意列表中并没有boolean和double类型!除非你定义了这两个类型,否则用在参数和返回值中就是错误的!

这也是PHP有点蛋疼的地方。平常使用时的double和float两个关键字几乎等同,例如doubleval是floatval的别名,is_double是is_float的别名,转换时用(double)和(float)效果相同。但是到了类型声明这里就不行,同样的情况出现在bool和boolean身上。

总结

目前PHP 7.2稳定版已经发布,建议在新项目中尽量使用PHP 7.1及后续版本。为了写出清晰和可维护的代码,推荐声明类型。建议引用类型或者string才使用null值,int/float等标量类型的参数尽量不要用null。func_get_argc等函数,如非必要,尽量不使用。

您可能感兴趣的文章:

  • PHP 页面编码声明方法详解(header或meta)
  • php学习笔记 类的声明与对象实例化
  • php数组声明、遍历、数组全局变量使用小结
  • php学习之 数组声明
  • PHP类的声明与实例化及构造方法与析构方法详解
  • php类声明和php类使用方法示例分享
  • php学习笔记之 函数声明
(0)

相关推荐

  • PHP类的声明与实例化及构造方法与析构方法详解

    本文实例讲述了PHP类的声明与实例化及构造方法与析构方法.分享给大家供大家参考,具体如下: <?php class human{ public static $leg=2; public $name = 'leo'; public $age = '25'; public function cry(){ } } $leo = new human(); print_r($leo); /*返回 human Object ( [name] => leo [age] => 25 ) */ //为什

  • php学习之 数组声明

    复制代码 代码如下: <?php /* * 一.数组的概述 * 1.数组的本质:管理和操作一组变量,成批处理 * 2.数组时复合类型(可以存储多个) * 3.数组中可以存储任意长度的数据,也可以存储任意类型的数据 * 4.数组可以完成其他语言数据结构的功能(链表,队列,栈,集合类) * * * * 二.数组的分类 * 数组中有多个单元,(单元称为元素) * 每个元素(下标[键]和值) * 单访问元素的时候,都是通过下标(键)来访问元素 * 1.一维数组,二维数组,三维数组...多维数组 * (数

  • php类声明和php类使用方法示例分享

    复制代码 代码如下: <?php /**php语言是支持面向对象编程的,对于面向对象的编程,学过java和C++的人都知道啊!      *如果不清楚的去baidu问一下就可以了.    */ //我们来定义一个类,定义类的关键字是 "class"        class computer { //在类里面可以创建方法,变量等 //定义一个加法        function add ($n1,$n2) { $sum = $n1 + $n2;            return

  • php学习笔记 类的声明与对象实例化

    复制代码 代码如下: <?php /* 类的声明 * 1.你要开发的是什么,确定写什么类 * 2.类中的成员一定要属于这个类 * [修饰类的关键字] class 类名{ * 成员属性: * 成员方法: * } * 3.在类中声明成员属性时,前面必须有修饰词,当不确定使用哪个词时,使用var或public * 一个文件只保存一个类,文件名中包含类名,文件:类名.class.php * 类名的写法: * 变量:aaaBbbCcc * 函数:aaaBbbCcc * 常量:AAABBBCCC * 类名:

  • php数组声明、遍历、数组全局变量使用小结

    php教程:数组声明,遍历,数组全局变量 复制代码 代码如下: <? /* * 一.数组的概述 * 1.数组的本质:管理和操作一组变量,成批处理 * 2.数组时复合类型(可以存储多个) * 3.数组中可以存储任意长度的数据,也可以存储任意类型的数据 * 4.数组可以完成其他语言数据结构的功能(链表,队列,栈,集合类) * * * * 二.数组的分类 * 数组中有多个单元,(单元称为元素) * 每个元素(下标[键]和值) * 单访问元素的时候,都是通过下标(键)来访问元素 * 1.一维数组,二维数

  • PHP 页面编码声明方法详解(header或meta)

    php的header来定义一个php页面为utf编码或GBK编码 php页面为utf编码 header("Content-type: text/html; charset=utf-8"); php页面为gbk编码 header("Content-type: text/html; charset=gb2312"); php页面为big5编码 header("Content-type: text/html; charset=big5"); 通常情况以

  • php学习笔记之 函数声明

    复制代码 代码如下: <?php /* 函数定义: * 1.函数是一个被命名的 * 2.独立的代码段 * 3.函数执行特定任务 * 4.并可以给调用它的程序返回一个值 * * 函数的优点: * 1.提高程序的重用性 * 2.提高程序的可维护性 * 3.可以提高开发效率 * 4.提高软件的可靠性 * 5.控制程序的复杂性 * * 函数的声明 * function 函数名(){ * * } * * function 函数名(参数1,参数2,参数...) * { * 函数体 * } * * funct

  • PHP各版本中函数的类型声明详解

    PHP7开始支持标量类型声明,强类型语言的味道比较浓.使用这个特性的过程中踩过两次坑:一次是声明boolean,最近是声明double.为避免以后继续犯类似错误,就把官方文档翻了一次.本文是看完后对PHP函数的类型声明使用做的一次总结. 从语法上,PHP的函数定义经过了几个时期: 远古时代(PHP 4) 定义一个函数非常的简单,使用 function name(args) {body} 的语法声明.不能指定参数和返回值类型,参数和返回值类型有无限种可能.这是到目前为止最常见的函数声明方式. 数组

  • nodejs中函数的调用实例详解

    一.调用本js文件中的函数 var http = require('http'); http.createServer(function (request,response){ response.writeHead(200, {'Contet-Type':'text/html;charset=utf-8'}); if(request.url!=='/favicon.ico'){ funl(response); response.end(''); } }).listen(8000); consol

  • Python中函数参数匹配模型详解

    当我们的函数接收参数为任意个,或者不能确定参数个数时,我们,可以利用 * 来定义任意数目的参数,这个函数调用时,其所有不匹配的位置参数会被赋值为元组,我们可以在函数利用循环或索引进行使用 def f(*args): # 直接打印元组参数 print(args) print('-'*20) # 循环打印元组参数 [print(i) for i in args] ... # 传递一个参数 f(1) print('='*20) # 传递5个参数 f(1, 2, 3, 4, 5) 示例结果: (1,)

  • Python3中函数参数传递方式实例详解

    本文实例讲述了Python3中函数参数传递方式.分享给大家供大家参考,具体如下: 之前在看北理工嵩天等老师的python3的课程,在第五周中老师讲到了函数的调用传递.老师讲了这样一个例子 #处理多个银行账户的余额信息 def addInterest(balances, rate): for i in range(len(balances)): balances[i] = balances[i] * (1+rate) def test(): amounts = [1000, 105, 3500,

  • Laravel5.5以下版本中如何自定义日志行为详解

    前言 在 Laravel 5.6 版本中日志行为可以很容易的进行自定义,而在5.5以下版本中日志行为自定义自由度并不是很高,但是项目有需求不能因为这个就强行将项目升级为5.6吧,况且作为一个稳定的项目升级框架大版本有可能会有很多坑,基于这些原因我尝试了对 Laravel 5.5 的日志进行改造以适应我的需求. Laravel 的日志行为大部分是在 Illuminate\Log\LogServiceProvider 中,我们可以看一下其中的代码片段: /** * Configure the Mon

  • javaScript的函数对象的声明详解

    写作缘由: 平时再用js写函数的时候,一般都是以惯例 function fn () {} 的方式来声明一个函数,在阅读一些优秀插件的时候又不免见到 var fn = function () {} 这种函数的创建,究竟他们用起来有什么区别呢,今天就本着打破砂锅问到底的精神,好好来说说这个让人神魂颠倒的--函数声明. 函数声明 函数声明示例代码 复制代码 代码如下: function fn () {     console.log('fn 函数执行..');     // code.. } 这样我们

  • OpenStack Mitaka 版本中的 domain 和 admin详解

    OpenStack 的 Keystone V3 中引入了 Domain 的概念.引入这个概念后,关于 admin 这个role 的定义就变得复杂了起来. 本文测试环境是社区 Mitaka 版本. 1. Domain,project,user,role,token 的概念和关系 1.1 概况 简单来说, Domain - 表示 project 和 user 的集合,在公有云或者私有云中常常表示一个客户 Group - 一个domain 中的部分用户的集合 Project - IT基础设施资源的集合

  • Swift编程中的一些类型转换方法详解

    验证一个实例的类型'类型转换'在 Swift 语言编程中.它是用来检查实例类型是否属于特定超类或子类或其自己的层次结构定义. Swift 类型转换提供两个操作符:"is" 检查值的类型和 'as' 将类型值转换为不同的类型值. 类型转换还检查实例类型是否符合特定的协议一致性标准. 定义一个类层次结构 类型转换用于检查实例的类型或者它属于特定类型.此外,检查类和它的子类层次结构来检查并转换这些实例,使之作为一个相同的层次结构. 复制代码 代码如下: class Subjects {   

  • .NET中的Timer类型用法详解

    在.NET FrameWork中有多个Timer,那么怎么根据实际情况进行选择确实是一个问题. 总体而言,计时器共有以下四种: 多线程计时器: 1 System.Threading.Timer 2 System.Timers.Timer 特殊环境的单线程计时器: 1 System.Windows.Forms.Timer(使用环境:Windows Forms Timer) 2 System.Windows.Threading.DispatcherTimer( 使用环境:WPF timer); 单线

  • Python中关于元组 集合 字符串 函数 异常处理的全面详解

    目录 元组 集合 字符串 1.字符串的驻留机制 2.常用操作 函数 1.函数的优点: 2.函数的创建:def 函数名([输入参数]) 3.函数的参数传递: 4.函数的返回值: 5.函数的参数定义: 6.变量的作用区域 7.递归函数:函数体内套用该函数本身 8.将函数存储在模块中 9.函数编写指南: Bug 1.Bug常见类型 2.常见异常类型 3.python异常处理机制 pycharm开发环境的调试 编程思想 (1)两种编程思想 (2)类和对象的创建 元组 元组是不可变序列 多任务环境下,同时

随机推荐