2012-10-15 20 views
8

Giả sử chúng ta có khối này:Objective-C thông số khối

int (^aBlock)(BOOL) = ^(BOOL param) { ... 

hiểu biết hiện tại của tôi, đó là: int Đầu tiên là kiểu trả về, (^aBlock)(BOOL) cho tên của phương pháp và các loại tham số của nó, và = ^(BOOL param) là tên của thông số bên trong khối ... cộng với loại thông số một lần nữa?

Tại sao cú pháp sao cho chúng tôi phải liệt kê loại tham số hai lần? Hai loại có thể khác nhau không?

Trả lời

11

Nó không phải là khá "liệt kê các tham số gõ hai lần" , bạn đang ở trong trường hợp đầu tiên khai báo loại biến số của biến số và trong trường hợp thứ hai, bạn đang xác định khối chữ. Sau đó, bạn đang gán chữ cho giá trị của biến. Bạn thậm chí có thể làm một cái gì đó như thế này, đó là tương đương và tốt hơn cho thấy một thực tế rằng đây là những thực sự hai tờ khai hoàn toàn độc lập, dù đã được gắn liền với một tuyên bố assign:

id thisBlock = ^id (id x, NSUInteger idx) { 
    NSLog(@"x = %@",x); 
    return x; 
}; 

id (^thatBlock)(id obj, NSUInteger index) = thisBlock; 

Thực tế rằng họ là độc lập với nhau các phương tiện khác có thể thậm chí không chính xác để cố gắng cung cấp một số loại chuyển đổi hoặc thừa kế thông tin nhập từ bên tay trái của biểu thức sang bên phải. Và có, các loại có thể khác nhau - xem xét mã này biên dịch và thực thi tốt:

id (^thatBlock)(NSArray *, NSDictionary *, NSString *) = ^id (id x, id y, id z) { 
    NSLog(@"x = %@",x); 
    return x; 
}; 

thatBlock(@[],@{},@""); 

Hy vọng điều này sẽ hữu ích!

+0

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

+0

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. –

1

Tại sao cú pháp sao cho chúng tôi phải liệt kê loại tham số hai lần?

Khối được thiết kế theo cách này, và do đó bạn có thể làm điều đó như thế này:

int (^aBlock)(BOOL); 

aBlock = ^(BOOL param) { 
    ... 
}; 

Nó chỉ thích

- (int)aMethodWithParam:(BOOL)param; 

- (int)aMethodWithParam:(BOOL)param { 
    ... 
} 

thể hai loại bao giờ có khác nhau?

Nope, và còn gì nữa, thứ tự của các loại nên giống nhau, ví dụ:

int (^aBlock)(BOOL, NSString*) = ^(BOOL param, NSString *aString) { 
    ... 
}; 

Và đây là một con số rõ ràng cho khối:

Image

2

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 đị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.)

+0

"Đoạn mã bạn đã đưa ra không phải là tuyên bố khối" - Quá đúng! Cảm ơn bạn, tôi có thể chỉnh sửa điều đó! – chm

-1

Theo Ry's Objective C Tutorial:

Blocks sử dụng tất cả các cơ chế tương tự như chức năng bình thường. Bạn có thể khai báo một biến khối giống như bạn khai báo một hàm.

NSInteger (^BlocksAddition)(NSInteger x,NSInteger y)=^NSInteger(NSInteger x, NSInteger y){ 

    return x+y; 
}; 

NSUInteger result=BlocksAddition(4,5); 
NSLog(@"Addition Result:%d",result); 
+0

Khi bạn sao chép văn bản từ tác phẩm của người khác, bạn cần phải nói văn bản đến từ đâu và liên kết ngược lại với nguồn gốc và bạn cũng cần phải trích dẫn chính xác các từ * không phải là của riêng bạn *. Nếu không, ** bạn đang phạm tội đạo văn **. Để biết thêm thông tin về cách tham chiếu đúng cách * những người khác làm việc * trong câu trả lời của bạn, vui lòng xem [Cách tham khảo tài liệu được viết bởi người khác] (http://stackoverflow.com/help/referencing). –