Mã đoạn trích bạn đã đưa ra không phải là tuyên bố khối: đó là tuyên bố khối và định nghĩa khối. Đầu tiên, bạn khai báo một định danh tên aBlock
:
int (^aBlock)(BOOL)
sau đó bạn xác định một khối:
^(BOOL param) { ...
Cả hai được phân tích và đánh giá riêng rẽ. Vì bạn đang gán một cái khác, trình biên dịch thực hiện kiểm tra kiểu để đảm bảo rằng biểu thức ở phía bên tay trái (khai báo aBlock
) có cùng kiểu với biểu thức ở phía bên tay phải (định nghĩa khối) .
Vì vậy, câu trả lời là, các phần này cần được đánh giá riêng. Vì định nghĩa khối đang được biên dịch theo cách riêng của nó, bạn phải bao gồm loại param
, bởi vì nếu không thì trình biên dịch sẽ không biết loại nó nên là gì. (Có, bạn có thể tạo ngoại lệ trong trường hợp này và xem qua nhiệm vụ đó, nhưng ở mọi nơi khác bằng ngôn ngữ C bạn khai báo một mã định danh bằng cách đưa ra một loại đầu tiên, vậy tại sao nó lại khác ở đây?)
Nhưng - bạn có thể nói - nếu đó là sự thật tại sao tôi không phải xác định loại trả về (int
) ở phía bên tay phải?
Rất sắc sảo của bạn. Câu trả lời là, khi viết một biểu thức khối, bạn không cần định nghĩa kiểu trả về, vì trình biên dịch có thể suy ra nó từ câu lệnh trả về (hoặc thiếu nó) bên trong khối.
(Vậy tại sao bạn phải bao gồm các loại trở lại với các định nghĩa chức năng? Vâng, lịch sử, tôi đoán. Định nghĩa ngôn ngữ lập trình được tạo ra bởi con người không hoàn hảo.)
Vâng, thật tuyệt vời, cảm ơn. Chỉ cần làm rõ, là đoạn mã thứ hai của bạn một ví dụ về chuyển giao thông tin gõ (và do đó cau mày)? – chm
Không, tôi chỉ minh họa rằng các loại giữa tay trái và tay phải có thể khác nhau và mã sẽ biên dịch và chạy. Không có nhiều loại kiểm tra với các khối khác với các loại trả về theo như tôi có thể nói thực sự. Không có sự chuyển tải thông tin nào vì điều đó không thực sự là một điều, tôi đã nói một chút lạ lùng, tôi đã cố gắng nói rằng ngay cả khi trình biên dịch đã cố gắng làm điều gì đó như vậy thì nó sẽ không nhất thiết phải đúng, vì có một số đặc điểm đa hình của các khối mà một tính năng như vậy sẽ gây trở ngại. –