2017-09-29 24 views
5

Tôi là người mới bắt đầu học php và học từ php.net. Một lưu ý trên trang đó (http://php.net/manual/en/class.traversable.php) nói rằng:Chúng tôi có thể sử dụng IterateAggregate hoặc Iterator trong vòng lặp foreach trong php không?

Internal lớp mà thực hiện giao diện này có thể được sử dụng trong một cấu trúc foreach và không cần phải thực hiện IteratorAggregate hoặc Iterator (built-in).

Điều này lưu ý là gì? Điều đó có nghĩa là chúng tôi có thể sử dụng IteratorAggregate hoặc Iterator bên trong vòng lặp foreach mà không có bất kỳ lớp nào hoặc có thể là tôi sai. Bất cứ ai có thể nói điều này lưu ý nói gì ??

Trả lời

2

Các IteratorAggregate là một giao diện để tạo ra một Iterator bên ngoài cho phép bạn đi qua lớp tùy chỉnh của bạn đối tượng sử dụng foreach:

class FooBarClass implements IteratorAggregate 
{ 
    public $property = "Nothing to see"; 

    public function __construct() 
    { 
    } 

    public function getIterator() 
    { 
     return new ArrayIterator($this); 
    } 
} 

$obj = new FooBar; 

foreach($obj as $key => $value) { 
    print(var_dump($key, $value) . "\n"); 
} 

Các Iterator cũng là một giao diện cho vòng lặp bên ngoài nhưng cho phép các lớp hoặc đối tượng của bạn tự lặp lại nội bộ:

class myIterator implements Iterator 
{ 
    private $position = 0; 
    private $array = array('one', 'two', 'three'); 

    function rewind() 
    { 
     $this->position = 0; 
    } 

    function current() 
    { 
     return $this->array[$this->position]; 
    } 

    function key() 
    { 
     return $this->position; 
    } 

    function next() 
    { 
     ++$this->position; 
    } 

    function valid() 
    { 
     return isset($this->array[$this->position]); 
    } 
} 

Tuy nhiên, bạn vẫn có thể duyệt qua các đối tượng của mình theo cách tương tự như với IteratorAggregate.

Sự khác biệt giữa cả hai là IteratorAggregate dễ triển khai hơn so với Iterator và thường nhanh hơn. Nhược điểm là nó chỉ dành cho traversal và không cung cấp các phương thức next(), key(), vv, vì chúng không được gọi trong suốt quá trình duyệt qua.

Trong khi Iterator (hoặc cụ thể hơn OuterIterator hoặc (dễ) hơn IteratorIterator) cho phép bạn có quyền kiểm soát tốt hơn đối với lặp qua đối tượng và thêm ngoại lệ tùy chỉnh vào(), khóa() hoặc trước() thất bại, bộ nhớ đệm(), v.v.

Lưu ý bạn đang đề cập đến có nghĩa là một số lớp học của PHP (được viết bằng mã C) có thể triển khai trực tiếp giao diện này. Bất kỳ lớp người dùng nào cần triển khai Traversable phải làm như vậy bằng cách triển khai IteratorAggregate hoặc Iterator hoặc một phần tử khác từ Traversable. Xem Pro PHP by Kevin McArthur p. 143f.

Giao diện Traversable chính nó là một giao diện cơ sở trừu tượng (không có phương pháp như được hiển thị trong tóm tắt giao diện) mà không thể được khởi tạo. Tuy nhiên, nó có thể được sử dụng để kiểm tra xem một lớp có thể đi ngang bằng cách sử dụng foreach hay không.

Traversable { 
} 

Phần nhầm lẫn là các đối tượng và mảng làm không thực hiện "traversable", nhưng can be traversed bởi foreach, nhưng bạn không thể kiểm tra tính tương thích foreach sử dụng một kiểm tra instanceof hoặc type hint.

$myarray = array('one', 'two', 'three'); 
$myobj = (object)$myarray; 

if (!($myarray instanceof \Traversable)) { 
    print "myarray is NOT Traversable"; 
} 
if (!($myobj instanceof \Traversable)) { 
    print "myobj is NOT Traversable"; 
} 

Như đã đề cập trước đó, mọi đối tượng đều có thể đi qua với foreach, nhưng sau đó bạn chỉ có thể truy cập các thuộc tính công khai. Trích dẫn từ cuốn hướng dẫn PHP trên Object Iteration:

PHP 5 cung cấp một cách cho các đối tượng được xác định do đó nó có thể lặp thông qua một danh sách các mục, với, ví dụ như một foreach tuyên bố. Theo mặc định, tất cả các thuộc tính hiển thị sẽ được sử dụng cho lần lặp lại .

Vì vậy, nếu bạn đóng gói một đối tượng có giá trị riêng tư và được bảo vệ và viết phương thức getter và setter để truy cập nó, bạn có thể yêu cầu lớp của bạn triển khai IteratorAggregate hoặc Iterator và viết logic. khi cần thiết.

Tóm lại, các đối tượng triển khai giao diện Traversable (thông qua Iterator hoặc IteratorAggregate) "hoạt động như một mảng". Tuy nhiên, không cần thiết phải lặp lại đối tượng. Nhưng bạn cần triển khai Iterator nếu bạn muốn thay đổi hành vi của chúng. Logic tương tự áp dụng cho các lớp dựng sẵn.

+0

Câu trả lời của bạn hoàn toàn khác với ** ghi chú ** trong câu hỏi tôi đã hỏi. Bạn có thể vui lòng giải thích ** lưu ý ** bằng những từ đơn giản được hỏi trong câu hỏi không? –

+0

Tôi nhờ bạn nhờ sự giúp đỡ. Một điều nhấn mạnh tôi rất nhiều, từ ** foreach ** trong ghi chú đó. Cho dù nó có nghĩa là nội bộ được xây dựng trong các lớp học thực hiện ** Traversable ** giao diện trực tiếp mà không cần thực hiện ** IteratorAggregate ** hoặc ** Iterator ** giao diện và sử dụng ** Traversable ** trực tiếp trong ** foreach ** loop? Hoặc có thể tôi đã sai nên bạn có thể nói không? –

+0

Từ ** foreach ** gây nhầm lẫn cho tôi và không biết kịch bản của ** foreach ** trong ** note ** này là gì. –

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