私はMac/iPhoneプログラミングとObjective-Cの初心者です。C#とJavaには「ジェネリック」というコレクションクラスがあり、そのメンバーは宣言された型のみになります。たとえば、C#では
Dictionary<int, MyCustomObject>
整数のキーと MyCustomObject 型の値のみを含めることができます。Objective-C にも同様のメカニズムは存在しますか?
ベストアンサー1
Xcode 7 では、Apple は Objective-C に「軽量ジェネリック」を導入しました。Objective-C では、型の不一致がある場合にコンパイラ警告が生成されます。
NSArray<NSString*>* arr = @[@"str"];
NSString* string = [arr objectAtIndex:0];
NSNumber* number = [arr objectAtIndex:0]; // Warning: Incompatible pointer types initializing 'NSNumber *' with an expression of type 'NSString *'
Swift コードでは、コンパイラ エラーが発生します。
var str: String = arr[0]
var num: Int = arr[0] //Error 'String' is not convertible to 'Int'
軽量ジェネリックは、NSArray、NSDictionary、NSSet で使用することを目的としていますが、独自のクラスに追加することもできます。
@interface GenericsTest<__covariant T> : NSObject
-(void)genericMethod:(T)object;
@end
@implementation GenericsTest
-(void)genericMethod:(id)object {}
@end
Objective-C は、コンパイラ警告を出して以前と同じように動作します。
GenericsTest<NSString*>* test = [GenericsTest new];
[test genericMethod:@"string"];
[test genericMethod:@1]; // Warning: Incompatible pointer types sending 'NSNumber *' to parameter of type 'NSString *'
ただし、Swift は Generic 情報を完全に無視します。(Swift 3 以降ではこれは当てはまりません。)
var test = GenericsTest<String>() //Error: Cannot specialize non-generic type 'GenericsTest'
これらの Foundation コレクション クラスを除き、Objective-C の軽量ジェネリックは Swift によって無視されます。軽量ジェネリックを使用するその他の型は、パラメーター化されていないものとして Swift にインポートされます。