Một "loại giao lộ" yêu cầu một giá trị để đáp ứng nhiều ràng buộc loại thay vì một ràng buộc duy nhất Show
Các loại giao lộ hiện không được hỗ trợ bởi ngôn ngữ. Thay vào đó, người ta phải sử dụng chú thích phpdoc và/hoặc lạm dụng các thuộc tính đã nhập [1] như có thể thấy trong ví dụ sau ___class Test { private ?Traversable $traversable = null; private ?Countable $countable = null; /** @var Traversable&Countable */ private $both = null; public function __construct($countableIterator) { $this->traversable =& $this->both; $this->countable =& $this->both; $this->both = $countableIterator; } } Việc hỗ trợ các kiểu giao nhau trong ngôn ngữ cho phép chúng tôi di chuyển nhiều thông tin kiểu hơn từ phpdoc sang chữ ký hàm, với những lợi thế thông thường mà điều này mang lại
Động lựcCó thể mô phỏng các loại giao lộ bằng cách tạo một giao diện mới kế thừa từ nhiều giao diện, một trường hợp như vậy là interface CountableIterator extends Iterator, Countable {}7 tích hợp mở rộng giao diện interface CountableIterator extends Iterator, Countable {}8 bằng cách thêm phương thức interface CountableIterator extends Iterator, Countable {}9 trên đó. Tuy nhiên, một trình vòng lặp cũng có thể đếm được, và nếu một hàm cần nhập theo yêu cầu như vậy thì cách duy nhất có thể hiện tại là tạo một giao diện mới______ 1 Điều này hoạt động, nhưng nếu chúng ta muốn một trình vòng lặp có thể đếm được và tìm kiếm được thì sao? ___interface SeekableCountableIterator extends CountableIterator, SeekableIterator {} Như vậy, mỗi yêu cầu mới đòi hỏi phải tạo ra nhiều giao diện mới có tính đến tất cả các kết hợp có thể Hơn nữa, lớp cần triển khai giao diện cụ thể và không thể chỉ dựa vào việc triển khai các giao diện cơ sở, nghĩa là việc giới thiệu các giao diện như vậy cần được phổ biến cho tất cả các lớp có liên quan, điều này có thể dễ xảy ra lỗi. Xem ví dụ này ___interface A {} interface B {} interface AB extends A, B {} class Test implements A, B {} function foo(AB $v) { var_dump($v); } foo(new Test()); Các loại giao lộ giải quyết những vấn đề này đề nghịHỗ trợ thêm cho các loại giao lộ thuần túy được chỉ định bằng cú pháp interface SeekableCountableIterator extends CountableIterator, SeekableIterator {}0 và có thể được sử dụng ở tất cả các vị trí hiện đang chấp nhận các loại___________số 8 Điều này có nghĩa là không thể kết hợp các loại giao lộ và liên kết với nhau, chẳng hạn như interface SeekableCountableIterator extends CountableIterator, SeekableIterator {}1, đây là phạm vi trong tương lai Các loại được hỗ trợChỉ các loại lớp (giao diện và tên lớp) được hỗ trợ bởi các loại giao nhau Cơ sở lý luận là đối với gần như tất cả các loại tiêu chuẩn sử dụng chúng trong một loại giao lộ sẽ dẫn đến một loại không bao giờ được thỏa mãn (e. g. ____________ 52) Việc sử dụng interface SeekableCountableIterator extends CountableIterator, SeekableIterator {}3 trong một loại giao lộ là không cần thiết vì interface SeekableCountableIterator extends CountableIterator, SeekableIterator {}4 tương ứng với interface SeekableCountableIterator extends CountableIterator, SeekableIterator {}5, vì vậy điều này không được phép Tương tự, sử dụng interface SeekableCountableIterator extends CountableIterator, SeekableIterator {}6 trong giao lộ dẫn đến loại không hợp lệ dư thừa, điều này có thể được nhìn thấy bằng cách mở rộng biểu thức loại interface SeekableCountableIterator extends CountableIterator, SeekableIterator {}7 Mặc dù giao lộ với interface SeekableCountableIterator extends CountableIterator, SeekableIterator {}8 có thể hợp lý (e. g. chuỗi&có thể gọi được), chúng tôi cho rằng điều đó là không khôn ngoan và chỉ ra một lỗi Tương tự, interface SeekableCountableIterator extends CountableIterator, SeekableIterator {}9, interface A {} interface B {} interface AB extends A, B {} class Test implements A, B {} function foo(AB $v) { var_dump($v); } foo(new Test());0 và interface A {} interface B {} interface AB extends A, B {} class Test implements A, B {} function foo(AB $v) { var_dump($v); } foo(new Test());1 khả thi về mặt kỹ thuật và có thể được sử dụng như một phần của giao lộ, nhưng áp đặt các hạn chế kỳ lạ đối với lớp con mà lớp cơ sở vi phạm hoặc lớp cơ sở đã đáp ứng các yêu cầu về loại trong trường hợp đó là dư thừa. những loại đó Do đó, ba loại cũng bị cấm vì chúng có khả năng chỉ ra một vấn đề về thiết kế Các loại trùng lặp và dư thừaĐể bắt một số lỗi đơn giản trong khai báo kiểu giao nhau, các kiểu dư thừa có thể được phát hiện mà không thực hiện tải lớp sẽ dẫn đến lỗi thời gian biên dịch. Điêu nay bao gôm
Điều này không đảm bảo rằng loại là "tối thiểu", vì làm như vậy sẽ yêu cầu tải tất cả các loại lớp đã sử dụng Ví dụ: nếu interface A {} interface B {} interface AB extends A, B {} class Test implements A, B {} function foo(AB $v) { var_dump($v); } foo(new Test());3 và interface A {} interface B {} interface AB extends A, B {} class Test implements A, B {} function foo(AB $v) { var_dump($v); } foo(new Test());4 là bí danh của lớp thời gian chạy, thì interface A {} interface B {} interface AB extends A, B {} class Test implements A, B {} function foo(AB $v) { var_dump($v); } foo(new Test());5 vẫn là một loại giao lộ hợp pháp, mặc dù nó có thể được giảm xuống thành interface A {} interface B {} interface AB extends A, B {} class Test implements A, B {} function foo(AB $v) { var_dump($v); } foo(new Test());3 hoặc interface A {} interface B {} interface AB extends A, B {} class Test implements A, B {} function foo(AB $v) { var_dump($v); } foo(new Test());4. Tương tự, nếu interface A {} interface B {} interface AB extends A, B {} class Test implements A, B {} function foo(AB $v) { var_dump($v); } foo(new Test());8, thì interface A {} interface B {} interface AB extends A, B {} class Test implements A, B {} function foo(AB $v) { var_dump($v); } foo(new Test());5 cũng là một loại giao lộ hợp pháp, mặc dù nó có thể được giảm xuống chỉ còn interface A {} interface B {} interface AB extends A, B {} class Test implements A, B {} function foo(AB $v) { var_dump($v); } foo(new Test());4___ interface CountableIterator extends Iterator, Countable {}9 gõ ngữ phápDo sự mơ hồ của trình phân tích cú pháp với việc khai báo tham số by-ref trong khi sử dụng trình phân tích cú pháp LR(1) hiện tại, ngữ pháp và từ vựng được sửa đổi để tạo các mã thông báo khác nhau cho ký tự class A { private Traversable&Countable $countableIterator; public function setIterator(Traversable&Countable $countableIterator): void { $this->countableIterator = $countableIterator; } public function getIterator(): Traversable&Countable { return $this->countableIterator; } }1 tùy thuộc vào việc nó có được theo sau bởi một biến (biến thể) hay không Do đó, ngữ pháp trông như sau ____________ 31phương saiCác loại giao lộ tuân theo các quy tắc phương sai PHP tiêu chuẩn đã được sử dụng để kiểm tra kiểu và kế thừa
Thay đổi duy nhất là cách các loại giao lộ tương tác với phân loại, với hai quy tắc bổ sung
Sau đây, một số ví dụ về những gì được phép và những gì không được đưa ra loại tài sảnCác loại thuộc tính là bất biến, có nghĩa là các loại phải giữ nguyên trong quá trình kế thừa. Tuy nhiên, loại “giống nhau” có thể được thể hiện theo những cách khác nhau Các loại giao lộ mở rộng khả năng trong khu vực này. Ví dụ: interface A {} interface B {} interface AB extends A, B {} class Test implements A, B {} function foo(AB $v) { var_dump($v); } foo(new Test());5 và interface CountableIterator extends Iterator, Countable {}93 đại diện cho cùng một loại. Ví dụ sau đây cho thấy một trường hợp phức tạp hơn____________ 44 Trong ví dụ này, giao điểm interface A {} interface B {} interface AB extends A, B {} class Test implements A, B {} function foo(AB $v) { var_dump($v); } foo(new Test());5 thực sự đại diện cho cùng loại với chỉ interface A {} interface B {} interface AB extends A, B {} class Test implements A, B {} function foo(AB $v) { var_dump($v); } foo(new Test());4 và kế thừa này là hợp pháp, mặc dù loại không giống nhau về mặt cú pháp Chính thức, chúng tôi đi đến kết quả này như sau. Đầu tiên, loại cha mẹ interface A {} interface B {} interface AB extends A, B {} class Test implements A, B {} function foo(AB $v) { var_dump($v); } foo(new Test());5 là một loại con của interface A {} interface B {} interface AB extends A, B {} class Test implements A, B {} function foo(AB $v) { var_dump($v); } foo(new Test());4. Thứ hai, interface A {} interface B {} interface AB extends A, B {} class Test implements A, B {} function foo(AB $v) { var_dump($v); } foo(new Test());4 là một kiểu con của interface A {} interface B {} interface AB extends A, B {} class Test implements A, B {} function foo(AB $v) { var_dump($v); } foo(new Test());5, bởi vì interface A {} interface B {} interface AB extends A, B {} class Test implements A, B {} function foo(AB $v) { var_dump($v); } foo(new Test());4 là một kiểu con của interface A {} interface B {} interface AB extends A, B {} class Test implements A, B {} function foo(AB $v) { var_dump($v); } foo(new Test());3 và interface A {} interface B {} interface AB extends A, B {} class Test implements A, B {} function foo(AB $v) { var_dump($v); } foo(new Test());4 là một kiểu con của interface A {} interface B {} interface AB extends A, B {} class Test implements A, B {} function foo(AB $v) { var_dump($v); } foo(new Test());4 Thêm và loại bỏ các loại giao lộViệc thêm các loại giao lộ ở vị trí trả về và xóa các loại giao lộ ở vị trí tham số là hợp pháp ____________ 55Phương sai của các thành viên giao điểm cá nhânTương tự như vậy, có thể hạn chế một phần tử giao nhau ở vị trí quay lại hoặc mở rộng một phần tử giao nhau ở vị trí tham số ____________ 56Tất nhiên, điều tương tự cũng có thể được thực hiện với nhiều thành phần giao điểm cùng một lúc và được kết hợp với việc thêm/xóa các loại đã đề cập trước đó Phương sai của loại nút giao với loại cấp bê tôngVì mục đích sử dụng chính của các loại giao lộ là để đảm bảo nhiều giao diện được triển khai, nên một lớp cụ thể hoặc giao diện triển khai tất cả các giao diện có trong giao lộ được coi là một kiểu con và do đó có thể được sử dụng khi cho phép đồng phương sai __________ 10Hơn nữa, có thể sử dụng một loại liên kết của các lớp/giao diện cụ thể khi mỗi thành viên của liên kết triển khai tất cả các giao diện trong giao lộ ____________ 11Lý do tại sao điều này có thể xảy ra là do sự kết hợp của các lớp/giao diện cụ thể ít tổng quát hơn tập hợp các lớp có thể thỏa mãn kiểu giao nhau Chế độ gõ cưỡng chếVì các loại tiêu chuẩn không được phép trong các loại giao nhau thuần túy, nên không cần xem xét chế độ nhập cưỡng chế Các loại tài sản và tài liệu tham khảoCác tham chiếu đến các thuộc tính đã nhập với các loại giao nhau tuân theo ngữ nghĩa được nêu trong các thuộc tính đã nhập RFC __________ 12 Sự phản xạĐể hỗ trợ các loại giao lộ, một lớp mới interface CountableIterator extends Iterator, Countable {}14 được thêm vào__________ 13 Phương thức interface CountableIterator extends Iterator, Countable {}15 trả về một mảng gồm các interface CountableIterator extends Iterator, Countable {}16 là một phần của giao lộ. Các loại có thể được trả về theo thứ tự tùy ý không khớp với khai báo loại ban đầu. Các loại cũng có thể bị biến đổi tương đương Ví dụ: loại interface CountableIterator extends Iterator, Countable {}17 có thể trả về các loại theo thứ tự interface CountableIterator extends Iterator, Countable {}18 thay vì. Yêu cầu duy nhất đối với Reflection API là loại được đại diện cuối cùng là tương đương Phương thức interface CountableIterator extends Iterator, Countable {}19 trả về một biểu diễn chuỗi của loại cấu thành một biểu diễn mã hợp lệ của loại trong ngữ cảnh không được đặt tên. Nó không nhất thiết phải giống như những gì đã được sử dụng trong mã gốc ví dụ__________ 14 Thay đổi không tương thích ngượcRFC này không chứa bất kỳ thay đổi không tương thích ngược nào Tuy nhiên, mã dựa trên interface CountableIterator extends Iterator, Countable {}16 hiện tại có thể cần được điều chỉnh để hỗ trợ xử lý mã sử dụng các loại giao lộ Phiên bản PHP được đề xuấtPhiên bản nhỏ tiếp theo, tôi. e. PHP8. 1 Phạm vi tương laiCác tính năng được thảo luận sau đây không phải là một phần của đề xuất này Các loại hỗn hợp (i. e. trộn các hiệp hội và các loại giao lộ)Mặc dù nguyên mẫu ban đầu [2] cho thấy rằng việc hỗ trợ interface SeekableCountableIterator extends CountableIterator, SeekableIterator {}1 mà không có bất kỳ nhóm nào có vẻ khả thi, nhưng vẫn còn nhiều cân nhắc khác (e. g. phản ánh), mà cụ thể là các quy tắc phương sai và kiểm tra, sẽ tăng lên đáng kể và dễ bị lỗi Cũng có ý kiến cho rằng các loại tổng hợp không nên dựa vào quyền ưu tiên của các công đoàn mà được nhóm lại với nhau một cách rõ ràng Vì vậy, chúng tôi xem xét một cách tiếp cận từng bước bằng cách chỉ cho phép giao lộ thuần túy trước tiên là cách tốt nhất về phía trước Nhập bí danhKhi các kiểu ngày càng trở nên phức tạp, có thể đáng để cho phép sử dụng lại các khai báo kiểu. Có hai cách chung để điều này có thể hoạt động. Một là bí danh địa phương, chẳng hạn như __________ 15Trong trường hợp này, interface CountableIterator extends Iterator, Countable {}42 là một biểu tượng chỉ hiển thị cục bộ và sẽ được phân giải thành loại interface CountableIterator extends Iterator, Countable {}43 ban đầu trong quá trình biên dịch Khả năng thứ hai là một typedef đã xuất ___interface CountableIterator extends Iterator, Countable {}6 Cần lưu ý rằng việc đưa vào đề xuất này sẽ thêm các cân nhắc bổ sung cho các bí danh loại vì có thể viết các loại hỗn hợp như thể nhóm được hỗ trợ. Tuy nhiên, cơ sở để hỗ trợ điều này có mặt trong đề xuất này Ý nghĩa thuần khiết trong PHP là gì?Hàm thuần túy là hàm chứa cả hai câu lệnh này về hàm. Hàm luôn đánh giá cùng một giá trị kết quả với (các) giá trị đối số giống nhau .
ArrayShape PHP là gì?các hàm php. Và #[ArrayShape] là sự phát triển rất được mong đợi của mô tả mảng của PHPDoc . Cũng sẽ có #[Không dùng nữa] , #[Pure] và #[Immutable].
Thuộc tính PHP là gì? Thuộc tính là gì. Thuộc tính là các phần tử siêu dữ liệu nhỏ được thêm vào cho các lớp PHP, hàm, bao đóng, thuộc tính lớp, phương thức lớp, hằng số và thậm chí trên các lớp ẩn danh . Nhận xét PHP DocBlock có lẽ là ví dụ quen thuộc nhất. Những nhận xét này phần nào được cấu trúc với "chú thích" @param. |