Objective-C中是否有强类型集合?

Ric*_*ich 138 generics collections objective-c strong-typing data-structures

我是Mac/iPhone编程和Objective-C的新手.在C#和Java中,我们有"泛型",集合类的成员只能是声明的类型.例如,在C#中

Dictionary<int, MyCustomObject>

只能包含整数和值为MyCustomObject类型的键.Objective-C中是否存在类似的机制?

Con*_*nor 210

在Xcode 7中,Apple已经为Objective-C引入了"Lightweight Generics".在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 *'
Run Code Online (Sandbox Code Playgroud)

在Swift代码中,它们会产生编译错误:

var str: String = arr[0]
var num: Int = arr[0] //Error 'String' is not convertible to 'Int'
Run Code Online (Sandbox Code Playgroud)

Lightweight Generics旨在与NSArray,NSDictionary和NSSet一起使用,但您也可以将它们添加到您自己的类中:

@interface GenericsTest<__covariant T> : NSObject

-(void)genericMethod:(T)object;

@end

@implementation GenericsTest

-(void)genericMethod:(id)object {}

@end
Run Code Online (Sandbox Code Playgroud)

Objective-C的行为与之前的编译器警告一样.

GenericsTest<NSString*>* test = [GenericsTest new];

[test genericMethod:@"string"];
[test genericMethod:@1]; // Warning: Incompatible pointer types sending 'NSNumber *' to parameter of type 'NSString *'
Run Code Online (Sandbox Code Playgroud)

但Swift将完全忽略通用信息.(在Swift 3+中不再适用.)

var test = GenericsTest<String>() //Error: Cannot specialize non-generic type 'GenericsTest'
Run Code Online (Sandbox Code Playgroud)

除了这些Foundation集合类之外,Swift还忽略了Objective-C轻量级泛型.使用轻量级泛型的任何其他类型都会导入到Swift中,就好像它们是未参数化的一样.

与Objective-C API交互

  • @rizzes.是的,它刚刚推出. (2认同)

Mar*_*c W 91

这个答案已经过时但仍具有历史价值.从Xcode 7开始,Connor在2015年6月8日的回答更为准确.


不,除非您想在自己的自定义集合类中使用C++模板,否则Objective-C中没有泛型(我强烈反对).

Objective-C将动态类型作为一个特性,这意味着运行时不关心对象的类型,因为所有对象都可以接收消息.将对象添加到内置集合时,它们只是被视为类型id.但不要担心,只需像正常那样向这些对象发送消息; 它会正常工作(当然,除非集合中的一个或多个对象不响应您发送的消息).

Java和C#等语言需要泛型,因为它们是强大的静态类型语言.与Objective-C的动态打字功能完全不同的球赛.

  • 我不同意"不要担心,只是向这些对象发送消息".如果将错误类型的对象放入集合中,而这些对象不响应这些消息,则会产生运行时错误.在其他语言中使用泛型可以避免编译时检查这个问题. (88认同)
  • 我也不同意不要担心的哲学 - 例如,如果你从NSArray中取出第一个项目并将其转换为NSNumber但该项目实际上是一个NSString,那你就搞砸了...... (36认同)
  • @RaffiKhatchadourian - 如果您正在编写iOS应用程序,那就没什么选择了.如果用Java编写一个很简单,并获得编写本机应用程序的所有好处,请相信我:我愿意. (13认同)
  • 我对此最大的抱怨不是动态语言与编译时检查,而是简单的开发人员沟通.我不能只看一个属性声明,知道它将返回什么类型的对象,除非它在某处记录. (11认同)
  • @ henning77是的,但Objective-C是比这些语言更动态的语言.如果您想要强大的类型安全性,请使用这些语言. (8认同)
  • @Marc:然后考虑改变措辞? (2认同)
  • @ericsoco或许Xamarin可能是一个不错的选择,如果你不介意花钱; C#恕我直言与Java相比具有许多优点,但缺点很少.与Objective-C相比......当谈到这些功能时,它比较"有点有利". (2认同)

小智 11

不,但为了使它更清晰,你可以用你想要存储的对象类型来评论它,我已经看到这样做了几次,当你需要在Java 1.4中编写一些东西时,例如:

NSMutableArray* /*<TypeA>*/ arrayName = ....
Run Code Online (Sandbox Code Playgroud)

要么

NSDictionary* /*<TypeA, TypeB>*/ dictionaryName = ...
Run Code Online (Sandbox Code Playgroud)


Mat*_*nes 6

Objective-C中没有泛型.

来自Docs

数组是有序的对象集合.Cocoa提供了几个数组类,NSArray,NSMutableArray(NSArray的子​​类)和NSPointerArray.


use*_*710 6

Apple在XCode 7中为ObjC添加了泛型:

@property NSArray<NSDate *>* dates;
- (NSArray<NSDate *> *)datesBeforeDate:(NSDate *)date;
- (void)addDatesParsedFromTimestamps:(NSArray<NSString *> *)timestamps;
Run Code Online (Sandbox Code Playgroud)

请参阅此处:https: //developer.apple.com/library/prerelease/mac/documentation/Swift/Conceptual/BuildingCocoaApps/WorkingWithCocoaDataTypes.html#//apple_ref/doc/uid/TP40014216-CH6-ID61


Kev*_*vin 5

这是在Xcode 7中发布的(最后!)

请注意,在Objective C代码中,它只是一个编译时检查; 只有将错误的类型放入集合或分配给类型属性才会出现运行时错误.

宣布:

@interface FooClass <T> : NSObject
@property (nonatomic) T prop;
@end
Run Code Online (Sandbox Code Playgroud)

使用:

FooClass<NSString *> *foo = [[FooClass alloc] init];
NSArray<FooClass<NSString *> *> *fooAry = [NSArray array];
Run Code Online (Sandbox Code Playgroud)

小心那些*.