このブロックがあるとしましょう:
int (^aBlock)(BOOL) = ^(BOOL param) { ...
これについての私の現在の理解は次のとおりです。最初int
は戻り型で(^aBlock)(BOOL)
あり、メソッドの名前とそのパラメーターの型を示し= ^(BOOL param)
、ブロック内のパラメーターの名前は...プラスパラメーターの型ですか?
パラメータタイプを2回リストする必要があるような構文はなぜですか?2つのタイプが異なる可能性はありますか?
このブロックがあるとしましょう:
int (^aBlock)(BOOL) = ^(BOOL param) { ...
これについての私の現在の理解は次のとおりです。最初int
は戻り型で(^aBlock)(BOOL)
あり、メソッドの名前とそのパラメーターの型を示し= ^(BOOL param)
、ブロック内のパラメーターの名前は...プラスパラメーターの型ですか?
パラメータタイプを2回リストする必要があるような構文はなぜですか?2つのタイプが異なる可能性はありますか?
これは、「パラメータタイプを2回リストする」ということではなく、最初のケースではブロック変数のタイプを宣言し、2番目のケースではブロックリテラルを定義しています。次に、変数の値にリテラルを割り当てます。このようなことを行うこともできます。これは、assignステートメントに関連付けられているにもかかわらず、これらが実際には2つの完全に独立した宣言であるという事実をよりよく示しています。
id thisBlock = ^id (id x, NSUInteger idx) {
NSLog(@"x = %@",x);
return x;
};
id (^thatBlock)(id obj, NSUInteger index) = thisBlock;
それらが互いに独立しているという事実は、式の左側から右側へのタイピング情報のある種の転送または継承を提供しようとすることさえおそらく正しくないことを意味します。そして、はい、タイプは異なる可能性があります-このコードは正常にコンパイルおよび実行されると考えてください:
id (^thatBlock)(NSArray *, NSDictionary *, NSString *) = ^id (id x, id y, id z) {
NSLog(@"x = %@",x);
return x;
};
thatBlock(@[],@{},@"");
お役に立てれば!
パラメータタイプを2回リストする必要があるような構文はなぜですか?
ブロックはこのように設計されているため、次のように実行できます。
int (^aBlock)(BOOL);
aBlock = ^(BOOL param) {
...
};
それはただ好きです
- (int)aMethodWithParam:(BOOL)param;
- (int)aMethodWithParam:(BOOL)param {
...
}
2つのタイプが異なる可能性はありますか?
いいえ、さらに、タイプの順序は同じである必要があります。つまり、次のようになります。
int (^aBlock)(BOOL, NSString*) = ^(BOOL param, NSString *aString) {
...
};
そして、これがブロックの明確な図です:
指定したコードスニペットはブロック宣言ではありません。ブロック宣言とブロック定義です。まず、次の名前の識別子を宣言しますaBlock
。
int (^aBlock)(BOOL)
次に、ブロックを定義します。
^(BOOL param) { ...
これらは両方とも個別に解析および評価されます。一方を他方に割り当てているため、コンパイラは型チェックを実行して、左側の式(aBlock
宣言)が右側の式(ブロック定義)と同じ型であることを確認します。
したがって、答えは、これらの部分を個別に評価する必要があるということです。ブロック定義はそれ自体でコンパイルされているparam
ため、タイプを含める必要があります。そうしないと、コンパイラーはそれがどのタイプであるかを認識できません。(はい、この場合は例外を作成して割り当てを確認できますが、C言語の他の場所では、最初に型を指定して識別子を宣言します。なぜここで異なるのですか?)
しかし、 -あなたは言うかもしれません-それが本当なら、なぜ私はint
右側にリターンタイプ()を定義する必要がなかったのですか?
あなたの非常に鋭い。答えは、ブロック式を作成するときに、コンパイラがブロック内のreturnステートメント(またはその欠如)からそれを推測できるため、return型を定義する必要がないということです。
(では、なぜ関数定義に戻り型を含める必要があるのでしょうか?まあ、歴史だと思います。プログラミング言語の定義は不完全な人間によって作成されました。)
RyのObjectiveCチュートリアルによると:
ブロックは、通常の機能と同じメカニズムをすべて使用します。関数を宣言するのと同じように、ブロック変数を宣言できます。
NSInteger (^BlocksAddition)(NSInteger x,NSInteger y)=^NSInteger(NSInteger x, NSInteger y){
return x+y;
};
NSUInteger result=BlocksAddition(4,5);
NSLog(@"Addition Result:%d",result);