zoukankan      html  css  js  c++  java
  • php 5.6 与之前版本不兼容中的数组属性定义辨析

    在php5.6官方文档的不兼容页(http://php.net/manual/zh/migration56.incompatible.php)中提到了几个与以前版本不兼容的情况,其中提到了为类定义数组属性时,不兼容的情况,原文及示例如下:

    在 PHP 5.6 之前的版本中,为类定义数组类型的属性时, 如果数组中同时使用了显式数组键和隐式数组键,并且显式的键和隐式的序列键相同, 那么数组的键将被覆盖。例如:

     1 <?php
     2 class C {
     3     const ONE = 1;
     4     public $array = [
     5         self::ONE => 'foo',
     6         'bar',
     7         'quux',
     8     ];
     9 }
    10 
    11 var_dump((new C)->array);
    12 ?>

    以上示例在PHP 5.5中输出:

    1 array(2) {
    2   [0]=>
    3   string(3) "bar"
    4   [1]=>
    5   string(4) "quux"
    6 }

    在PHP 5.6中输出:

    array(3) {
      [1]=>
      string(3) "foo"
      [2]=>
      string(3) "bar"
      [3]=>
      string(4) "quux"
    }
    以上的例子,其实是非常特例的情况,其出现的前提条件有几条:
    1. 必须是为类定义数组属性,并且是在类变量定义时初始化该属性的情况;
    2. 一定是显式数组键在前,隐式数组键在后,隐式数组键对与自身位置相同的显示数组键的值的覆盖的情况;如果隐式数组键在前,显式数组键定义在后,则覆盖是一定会发生的,与版本无关;
    3. 显式数组键必须是常量(包括类常量)方式,如果是字面量常量,则无论什么版本,在以上情况下,都不会出现隐式数组键覆盖显式数组键;
    考察以下示例在PHP 5.5中的输出:
    1.1 非类数组成员定义:
    1 $array = [
    2 ONE=>'foo',
    3  'bar',
    4  'quux'
    5 ];
    6 var_dump($array);

    输出:

    array(3) {
      [1] =>
      string(3) "foo"
      [2] =>
      string(3) "bar"
      [3] =>
      string(4) "quux"
    }

    1.2 非初始化时赋值:

    1 define('ONE', 1);
    2 class C {
    3 public $array;
    4 }
    5 $c = new C;
    6 $c->array = [ONE=>'foo','bar','quux'];
    7 var_dump($c->array);

    输出:

    array(3) {
      [1] =>
      string(3) "foo"
      [2] =>
      string(3) "bar"
      [3] =>
      string(4) "quux"
    }
     1 define('ONE', 1);
     2 class C {
     3 const ONE = 1;
     4  public $array;
     5  public function __construct() {
     6 $this->array = array(
     7 'bar',
     8  ONE => 'foo',
     9  'quux',
    10  );
    11  }
    12 }
    13 $c = new C;
    14 var_dump($c->array);

    输出:

    array(3) {
      [0] =>
      string(3) "bar"
      [1] =>
      string(3) "foo"
      [2] =>
      string(4) "quux"
    }

    2. 显式键对隐式键的覆盖:

     1 define('ONE', 1);
     2 class C {
     3 const ONE = 1;
     4  public $array = array(
     5 'bar',
     6  'quux',
     7  ONE => 'foo',
     8  'guru'
     9  );
    10 }
    11 $c = new C;
    12 var_dump((new C)->array);

    输出:

    array(3) {
      [0] =>
      string(3) "bar"
      [1] =>
      string(3) "foo"
      [2] =>
      string(4) "guru"
    }

    3. 字面量常量作为显式键名:

     1 class C {
     2 public $array = array(
     3 'bar',
     4  'quux',
     5  1 => 'foo',
     6  'guru'
     7  );
     8 }
     9 $c = new C;
    10 var_dump((new C)->array);

    输出:

    array(3) {
      [0] =>
      string(3) "bar"
      [1] =>
      string(3) "foo"
      [2] =>
      string(4) "guru"
    }
    1 class C {
    2 public $array = array(
    3 1 => 'foo',
    4  'bar',
    5  'quux',
    6  );
    7 }
    8 $c = new C;
    9 var_dump((new C)->array);

    输出:

    array(3) {
      [1] =>
      string(3) "foo"
      [2] =>
      string(3) "bar"
      [3] =>
      string(4) "quux"
    }
    其实本质上,这是一个隐藏的很深的小bug。
    在数组的定义中,如果有部分单元指定了数字键名,其后的隐式键名会延续此前最大数字(包括隐式或显式)键名,而不应产生隐式键名覆盖显式数字键名情况,无论显式键名是字面量常量还是符号常量。
    见官方手册数组一节:http://php.net/manual/zh/language.types.array.php:
    1 <?php
    2 $array = array(
    3          "a",
    4          "b",
    5     6 => "c",
    6          "d",
    7 );
    8 var_dump($array);
    9 ?>

    以上例程会输出:

    array(4) {
      [0]=>
      string(1) "a"
      [1]=>
      string(1) "b"
      [6]=>
      string(1) "c"
      [7]=>
      string(1) "d"
    }
    只不过,5.6之前的版本在实现为类初始化数组成员时,用符号常量作数字键,对部分单元进行命名,出现了与数组语义定义不符的情况。
    鉴于此种情况极其少见,故其影响较小,但一旦出现,则由此引起的bug极其难查。
  • 相关阅读:
    [Swift]LeetCode128. 最长连续序列 | Longest Consecutive Sequence
    [Swift]LeetCode126. 单词接龙 II | Word Ladder II
    [Swift]LeetCode127. 单词接龙 | Word Ladder
    [Xcode 实际操作]二、视图与手势-(6)给图像视图添加阴影效果
    [Swift]LeetCode124. 二叉树中的最大路径和 | Binary Tree Maximum Path Sum
    [Xcode 实际操作]二、视图与手势-(5)给图像视图添加圆角效果
    [Swift]LeetCode123. 买卖股票的最佳时机 III | Best Time to Buy and Sell Stock III
    [Swift]LeetCode120. 三角形最小路径和 | Triangle
    [Java]LeetCode117. 填充同一层的兄弟节点 II | Populating Next Right Pointers in Each Node II
    话说美国崛起
  • 原文地址:https://www.cnblogs.com/matchless/p/4751876.html
Copyright © 2011-2022 走看看