smilefish1987 / blogs

the blogs of me
1 stars 0 forks source link

PHP 5.4 新增特性 #8

Open smilefish1987 opened 9 years ago

smilefish1987 commented 9 years ago

PHP 5.4 新增特性

PHP 5.4 的新增特性可以参考 PHP手册,具体的特性列表如下:

  1. 新增支持 traits PHP 是单继承的语言。自 PHP 5.4.0 起,PHP 实现了代码复用的一个方法,称为 traits。 Traits 是一种为类似 PHP 的单继承语言而准备的代码复用机制。Trait 为了减少单继承语言的限制, 使开发人员能够自由地在不同层次结构内独立的类中复用方法集。Traits 和类组合的语义是定义了一 种方式来减少复杂性,避免传统多继承和混入类(Mixin)相关的典型问题。 Trait 和一个类相似,但仅仅旨在用细粒度和一致的方式来组合功能。Trait 不能通过它自身来实例化 它为传统继承增加了水平特性的组合;也就是说,应用类的成员不需要继承
  2. 新增短数组语法 例如: $a = [1,2,3] 或者 $b = ['a'=>1,'b'=>2]
  3. 新增支持对函数返回数组的成员访问解析 可以通过表达式 foo()[0],访问foo()函数返回的数组的第一个元素
  4. 现在 闭包 支持 $this
  5. 现在不管是否设置 short_open_tag php.ini 选项,<?= 将总是可用
  6. 新增在实例化时访问类成员 可以通过 (new Foo)->bar() 这样的表达式访问类成员
  7. 现在支持 Class::{expr}() 语法
  8. 新增二进制直接量 可以通过0b开头定义二进制字面量,例如: $b = 0b001001101;
  9. 改进解析错误信息和不兼容参数的警告
  10. SESSION 扩展现在能追踪文件的 上传进度
  11. 内置用于开发的 CLI 模式的 web server 可以通过php -S host:port的方式启动内置web server

namespace Name\TraitTest{
    trait AddAndSub{
        function add($a,$b){
            return $a+$b;
        }

        function sub($a,$b){
            return $a-$b;
        }

        function hello()
        {
            echo "trait hello()",PHP_EOL;
        }
    }

    class Base{
        function hello(){
            echo "Base hello()",PHP_EOL;
        }
    }

    class Test extends Base{
        use AddAndSub;
    }

    class Smile extends Base{
        use AddAndSub;
        function hello(){
            echo "Smile hello()",PHP_EOL;
        }
    }

    // PHP Fatal error:  Cannot instantiate trait Name\TraitTest\AddAndSub
    //$a = new AddAndSub();

    $test = new Test();
    echo  $test->add(1,2),PHP_EOL;
    echo  $test->sub(10,1),PHP_EOL;

    $smile = new Smile();
    echo $smile->add(999,123),PHP_EOL;
    echo $smile->sub(1000,23),PHP_EOL;

    /* 从基类继承的成员被 trait 插入的成员所覆盖。优先顺序是来自当前类的成员覆盖了 trait 的
方法,而 trait 则覆盖了被继承的方法 */
    echo  $test->hello(),PHP_EOL; 
    echo $smile->hello(),PHP_EOL;

    //  多个 trait,通过逗号分隔,在 use 声明列出多个 trait,可以都插入到一个类中

    trait Hello{
        public function hello(){
            echo "Hello",PHP_EOL;
        }
    }

    trait World{
        public function world(){
            echo "World",PHP_EOL;
        }
    }

    class HelloWorld{
        use Hello,World;
    }

    $helloWorld = new HelloWorld();
    $helloWorld->hello();
    $helloWorld->world();

    /* 如果两个 trait 都插入了一个同名的方法,如果没有明确解决冲突将会产生一个致命错误。
    为了解决多个 trait 在同一个类中的命名冲突,需要使用 insteadof 操作符来明确指定使用
     冲突方法中的哪一个。
    以上方式仅允许排除掉其它方法,as 操作符可以将其中一个冲突的方法以另一个名称来引入*/
    trait A{
        public function sayHello(){
            echo "A",PHP_EOL;
        }
    }

    trait B{
        public function sayHello(){
            echo "B",PHP_EOL;
        }
    }

    class TestInsteadof{
        use A,B{
            B::sayHello insteadof A;
        }
    }

    $ti = new TestInsteadof();
    $ti->sayHello();

    class TestAlians{
        use A,B{
            A::sayHello insteadof B;
            B::sayHello as hello;
        }
    }

    $ta = new TestAlians();
    $ta->sayHello();
    $ta->hello();

    //使用 as 语法还可以用来调整方法的访问控制

    trait T1{
        public function sayHello(){
            echo "Hello,world!";
        }
    }

    class Test1{
        use T1{ sayHello as protected;}
    }

    class Test2{
        use T1{ sayHello as private myPrivateHello;}
    }

    $test1 = new Test1();
    //$test1->sayHello(); // 错误

    $test2 = new Test2();
    $test2->sayHello();
    //$test2->myPrivateHello(); // 错误

    /* 从 trait 来组成 trait,在 trait 定义时通过使用一个或多个 trait,它能够组合其它 trait 中的
部分 或全部成员 */

    trait TraitHelloWorld{
        use Hello,World;
    }

    class Test3{
        use TraitHelloWorld;
    }

    $test3 = new Test3();
    $test3->hello();
    $test3->world();

    // Trait 的抽象成员,为了对使用的类施加强制要求,trait 支持抽象方法的使用

    trait TestAB{
        public function hello(){
            echo "hello",PHP_EOL;
        }

        abstract public function test();
    }

    class MyTestAB{
        use TestAB;

        public function test(){
            echo "just test",PHP_EOL;
        }
    }

    $myTestab = new MyTestAB();
    $myTestab->hello();
    $myTestab->test();

    //Trait 的静态成员,Trait中可以定义静态方法,方法中还能定义静态变量

    trait Counter{
        public function inc(){
            static $count = 0;
            $count++;
            echo $count,PHP_EOL;
        }

        public static function m(){
            echo "just test in m method",PHP_EOL;
        }
    }

    class C1{
        use Counter;
    }

    class C2{
        use Counter;
    }

    $c = new C1();
    $c->inc();
    C1::m();
    $c2 = new C2();
    $c2->inc();

    /*Trait中同样可以定义属性,如果 trait 定义了一个属性,那类将不能定义同样名称的属性,
     否则会产生一个错误。如果该属性在类中的定义与在 trait 中的定义兼容(同样的可见性和
     初始值) 则错误的级别是 E_STRICT,否则是一个致命错误 */

    trait PropertyTrait{
        public $data = 10;
        public static $m = 123;
    }

    class C3{
        use PropertyTrait;
    }

    $c3 = new C3();
    echo $c3->data,PHP_EOL;
    echo C3::$m,PHP_EOL;
}