2010-10-01 29 views
14

Có cách nào để thêm nhiều hơn một loại gợi ý cho một phương thức không? Ví dụ, foo (param) phải nhận một thể hiện của chuỗi HOẶC bar OR baz.Có thể chỉ định nhiều hơn một gợi ý loại cho một tham số không?

+0

Loại gợi ý không hỗ trợ chuỗi vô hướng; chỉ cần chỉ ra điều đó. – Qix

+0

@Qix Bây giờ chúng ta nên đề cập rằng [PHP không hỗ trợ gợi ý loại vô hướng như của PHP 7.0.0] (http://php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration). – faintsignal

Trả lời

6

Type hinting chỉ cho phép một gợi ý cho mỗi thông số (và cũng có thể, gợi ý cần là array hoặc tên lớp, bạn không thể gợi ý string), nhưng bạn có thể thực hiện việc này bằng cách kiểm tra loại tham số trong hàm của bạn , sử dụng get_class:

function foo($param) 
{ 
    if (!(is_string($param) || in_array(get_class($param), array("Bar", "Baz"))) 
    { 
    // invalid type for $param! 
    } 
} 

bạn thậm chí có thể sử dụng trigger_error để có nó thất bại với một lỗi PHP (như nó sẽ nếu một loại gợi ý thất bại) nếu bạn muốn.

+3

Tôi khuyên bạn nên ném 'InvalidArgumentException', để bạn ít nhất có thể khôi phục từ lỗi ... – ircmaxell

+1

@ircmaxell Tôi chỉ trình diễn cách OP * có thể * sao chép cách gợi ý kiểu làm việc. –

+0

Tôi không nói không phải 'trigger_error'. Tất cả phụ thuộc vào phong cách của bạn (và không có gì sai khi sử dụng 'trigger_error'). Tôi thích ngoại lệ, vì vậy tôi sử dụng 'InvalidArgumentException'. Nếu mục tiêu của bạn là bắt chước các gợi ý về loại, thì bằng mọi cách kích hoạt một lỗi nghiêm trọng ... – ircmaxell

22

Không thể thực thi (ngoại trừ bên trong phương thức). Bạn chỉ có thể cung cấp một gợi ý kiểu duy nhất, và chỉ cho các đối tượng/giao diện và mảng (kể từ PHP 5.1).

Bạn có thể/tuy nhiên nên ghi lại nó trong phương pháp của bạn, tức là:

/** 
* @param string|Bar|Baz $param1 
*/ 
function foo($param1); 
+3

+1 cho tài liệu – Hannes

10

Đây là một sử dụng interfaces. Nếu bạn muốn chắc chắn rằng đối tượng có một phương pháp ->foobar($baz), bạn có thể mong đợi một giao diện:

interface iFooBar { 
    public function foobar($baz); 
} 

class Foo implements iFooBar { 
    public function foobar($baz) { echo $baz; } 
} 
class Bar implements iFooBar { 
    public function foobar($baz) { print_r($baz); } 
} 

function doSomething(iFooBar $foo) { 
    $foo->foobar('something'); 
} 

Sau đó, khi gọi, chúng sẽ làm việc:

doSomething(new Foo()); 
doSomething(new Bar()); 

Những sẽ không:

doSomething(new StdClass()); 
doSomething('testing'); 
+0

Khá tuyệt! Cũng có các loại SPL (thử nghiệm): http://pl.php.net/manual/en/book.spl-types.php – joao

+0

giống như cách tôi đã làm. – ITroubs

+0

@joao: SPLTypes sẽ không hoạt động trên 5.3 (Họ sử dụng các cuộc gọi c không được chấp nhận). Cộng với bản cập nhật cuối cùng là vào năm 2008, do đó, khá an toàn để nói rằng nó không phải là hiện tại ... – ircmaxell

5

Câu hỏi hay. Nó áp dụng cho cả hai tài liệu IDE và PHP 5 Type Hinting. Bạn phải nhớ rằng trong OO polymorphism là bạn của bạn.

Nếu bạn tạo một lớp cơ sở và mở rộng chúng, gợi ý loại của bạn sẽ là lớp cơ sở ... tất cả các lớp mở rộng sẽ hoạt động. Xem ví dụ bên dưới.

// 
$test = new DUITest(); 

// Calls below will work because of polymorphism 
echo $test->test(new Molecule()) . '<br/>'; 
echo $test->test(new Vodka()) . '<br/>'; 
echo $test->test(new Driver()) . '<br/>'; 
echo $test->test(new Car()) . '<br/>'; 

// Will not work because different data type 
echo $test->test(new Pig()) . '<br/>'; 
echo $test->test(new Cop()) . '<br/>'; 
echo $test->test('test') . '<br/>'; 
echo $test->test(array()) . '<br/>'; 



/** 
* Class to test 
*/ 
class DUITest { 

    public function __construct() { 
     ; 
    } 

    /** 
    * Using type-hinting 
    * 
    * See below link for more information 
    * @link http://www.php.net/manual/en/language.oop5.typehinting.php 
    * 
    * @param Molecule|Car|Driver|Vodka $obj 
    */ 
    public function test(Molecule $obj) { 
     echo $obj; 
    } 

} 

/** 
* Base Class 
*/ 
class Molecule { 

    public function __construct() {} 

    /** 
    * Outputs name of class of current object 
    * @return <type> 
    */ 
    public function __toString() { 
     return get_class($this); 
    } 

} 

class Car extends Molecule {} 

class Driver extends Molecule {} 

class Vodka extends Molecule {} 

class Pig {} 
class Cop extends Pig{} 
8

Tại thời điểm viết bài này, không có hỗ trợ cho nhiều loại rõ ràng. Bạn phải dựa vào tài liệu và hệ thống kiểu động của PHP.

Tuy nhiên, tôi có đề xuất chủ yếu chưa hoàn chỉnh cho union types. Đó là nhắm mục tiêu 7.NEXT (tại thời điểm viết bài này là 7.1) hoặc 8 (tùy điều kiện nào đến trước).

Đây là một ví dụ đơn giản của một cái gì đó mà tôi nghĩ rằng sẽ rất có giá trị: array | Traversable:

function map(callable $fn, array|Traversable $input) { 
    foreach ($input as $key => $value) { 
     yield $key => $fn($value); 
    } 
} 

Thật không may là RFC đã không vượt qua; tuy nhiên đối với loại cụ thể array|Traversable hiện có loại iterable chính xác là như vậy.

Các vấn đề liên quan