PHP中的型別約束介紹

lankecms發表於2016-04-19

PHP的類方法和函式中可實現型別約束,但引數只能指定類、陣列、介面、callable 四種型別,引數可預設為NULL,PHP並不能約束標量型別或其它型別。

如下示例:

複製程式碼程式碼如下:

<?php
 
class Test
{
    public function test_array(array $arr)
    {
        print_r($arr);
    }
 
    public function test_class(Test1 $test1 = null)
    {
        print_r($test1);
    }
 
    public function test_callable(callable $callback, $data)
    {
        call_user_func($callback, $data);
    }
 
    public function test_interface(Traversable $iterator)
    {
        print_r(get_class($iterator));
    }
 
    public function test_class_with_null(Test1 $test1 = NULL)
    {
 
    }
}
 
class Test1{}
 
$test = new Test();
 
//函式呼叫的引數與定義的引數型別不一致時,會丟擲一個可捕獲的致命錯誤。
 
$test->test_array(array(1));
$test->test_class(new Test1());
$test->test_callable('print_r', 1);
$test->test_interface(new ArrayObject(array()));
$test->test_class_with_null();

那麼對於標量型別如何約束呢?

PECL擴充套件庫中提供了SPL Types擴充套件實現interger、float、bool、enum、string型別約束。

複製程式碼程式碼如下:

$int  = new  SplInt ( 94 );
 
try {
     $int  =  'Try to cast a string value for fun' ;
} catch ( UnexpectedValueException $uve ) {
    echo  $uve -> getMessage () .  PHP_EOL ;
}
 
echo  $int  .  PHP_EOL ;
/*
執行結果:
Value not an integer
94
*/

SPL Types會降低一定的靈活性和效能,實際專案中三思而行。





PHP 5 可以使用型別約束。函式的引數可以指定只能為物件(在函式原型裡面指定類的名字),php 5.1 之後也可以指定只能為陣列。 注意,即使使用了型別約束,如果使用NULL作為引數的預設值,那麼在呼叫函式的時候依然可以使用NULL作為實參。

Example #1 型別約束示例

<?php
//如下面的類
class MyClass
{
    
/**
     * 測試函式
     * 第一個引數必須為類OtherClass的一個物件
     */
    
public function test(OtherClass $otherclass) {
        echo 
$otherclass->var;
    }


    
/**
     * 另一個測試函式
     * 第一個引數必須為陣列 
     */
    
public function test_array(array $input_array) {
        
print_r($input_array);
    }
}

//另外一個類
class OtherClass {
    public 
$var 'Hello World';
}
?>

函式呼叫的引數與定義的引數型別不一致時,會丟擲一個致命錯誤。

<?php
// 兩個類的物件
$myclass = new MyClass;
$otherclass = new OtherClass;

// 致命錯誤:引數1必須是類OtherClass的一個物件
$myclass->test('hello');

// 致命錯誤:引數1必須為類OtherClass的一個例項
$foo = new stdClass;
$myclass->test($foo);

// 致命錯誤:引數1不能為null
$myclass->test(null);

// 正確:輸出 Hello World 
$myclass->test($otherclass);

// 致命錯誤:引數1必須為陣列
$myclass->test_array('a string');

// 正確:輸出 陣列
$myclass->test_array(array('a''b''c'));
?>

型別約束不只是用在類的成員函式裡,也能使用在函式裡。

<?php
// 如下面的類
class MyClass {
    public 
$var 'Hello World';
}

/**
 * 測試函式
 * 第一個引數必須是類MyClass的一個物件
 */
function MyFunction (MyClass $foo) {
    echo 
$foo->var;
}

// 正確
$myclass = new MyClass;
MyFunction($myclass);
?>

型別約束允許NULL值:

<?php

/* 接受NULL值 */
function test(stdClass $obj NULL) {

}

test(NULL);
test(new stdClass);

?>

型別約束只支援物件 和 陣列(php 5.1之後)兩種型別。而不支援整型 和 字串型別。


相關文章