Objective-C 中是否有强类型集合?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/848641/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Are there strongly-typed collections in Objective-C?
提问by Rich
I'm new to Mac/iPhone programming and Objective-C. In C# and Java we have "generics", collection classes whose members can only be of the type declared. For example, in C#
我是 Mac/iPhone 编程和 Objective-C 的新手。在 C# 和 Java 中,我们有“泛型”,即其成员只能是声明类型的集合类。例如,在 C# 中
Dictionary<int, MyCustomObject>
Dictionary<int, MyCustomObject>
can only contain keys that are integers and values that are of type MyCustomObject. Does a similar mechanism exist in Objective-C?
只能包含整数键和 MyCustomObject 类型的值。Objective-C 中是否存在类似的机制?
回答by Connor
In Xcode 7, Apple has introduced 'Lightweight Generics' to Objective-C. In Objective-C, they will generate compiler warnings if there is a type mismatch.
在 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 *'
And in Swift code, they will produce a compiler error:
而在 Swift 代码中,它们会产生编译器错误:
var str: String = arr[0]
var num: Int = arr[0] //Error 'String' is not convertible to 'Int'
Lightweight Generics are intended to be used with NSArray, NSDictionary and NSSet, but you can also add them to your own classes:
轻量级泛型旨在与 NSArray、NSDictionary 和 NSSet 一起使用,但您也可以将它们添加到您自己的类中:
@interface GenericsTest<__covariant T> : NSObject
-(void)genericMethod:(T)object;
@end
@implementation GenericsTest
-(void)genericMethod:(id)object {}
@end
Objective-C will behave like it did before with compiler warnings.
Objective-C 会像以前一样运行编译器警告。
GenericsTest<NSString*>* test = [GenericsTest new];
[test genericMethod:@"string"];
[test genericMethod:@1]; // Warning: Incompatible pointer types sending 'NSNumber *' to parameter of type 'NSString *'
but Swift will ignore the Generic information completely. (No longer true in Swift 3+.)
但是 Swift 会完全忽略 Generic 信息。(在 Swift 3+ 中不再适用。)
var test = GenericsTest<String>() //Error: Cannot specialize non-generic type 'GenericsTest'
Aside from than these Foundation collection classes, Objective-C lightweight generics are ignored by Swift. Any other types using lightweight generics are imported into Swift as if they were unparameterized.
除了这些 Foundation 集合类之外,Objective-C 轻量级泛型被 Swift 忽略。任何其他使用轻量级泛型的类型都被导入到 Swift 中,就好像它们没有参数化一样。
回答by Marc W
This answer is outdated but remains for historical value. As of Xcode 7, Connor's answer from Jun 8 '15 is more accurate.
这个答案已经过时,但仍然具有历史价值。从 Xcode 7 开始,Connor 在 2015 年 6 月 8 日的回答更加准确。
No, there are no generics in Objective-C unless you want to use C++ templates in your own custom collection classes (which I strongly discourage).
不,Objective-C 中没有泛型,除非您想在自己的自定义集合类中使用 C++ 模板(我强烈反对)。
Objective-C has dynamic typing as a feature, which means that the runtime doesn't care about the type of an object since all objects can receive messages. When you add an object to a built-in collection, they are just treated as if they were type id. But don't worry, just send messages to those objects like normal; it will work fine (unless of course one or more of the objects in the collection don't respond to the message you are sending).
Objective-C 具有动态类型作为特性,这意味着运行时不关心对象的类型,因为所有对象都可以接收消息。当您将对象添加到内置集合时,它们只会被视为 type id。不过不用担心,像往常一样向那些对象发送消息即可;它会正常工作(当然,除非集合中的一个或多个对象不响应您发送的消息)。
Generics are needed in languages such as Java and C# because they are strong, statically typed languages. Totally different ballgame than Objective-C's dynamic typing feature.
Java 和 C# 等语言需要泛型,因为它们是强大的静态类型语言。与 Objective-C 的动态打字功能完全不同的球赛。
回答by Mark Rhodes
No, but to make it clearer you can comment it with the type of object you want to store, I've seen this done a few times when you need to write something in Java 1.4 nowadays) e.g.:
不,但为了更清楚,您可以使用要存储的对象类型对其进行评论,当您现在需要在 Java 1.4 中编写某些内容时,我已经多次看到这样做了)例如:
NSMutableArray* /*<TypeA>*/ arrayName = ....
or
或者
NSDictionary* /*<TypeA, TypeB>*/ dictionaryName = ...
回答by Matthew Vines
There are no generics in Objective-C.
Objective-C 中没有泛型。
Arrays are ordered collections of objects. Cocoa provides several array classes, NSArray, NSMutableArray (a subclass of NSArray), and NSPointerArray.
数组是对象的有序集合。Cocoa 提供了几个数组类,NSArray、NSMutableArray(NSArray 的子类)和 NSPointerArray。
回答by user1259710
Apple has added generics to ObjC in XCode 7:
Apple 在 XCode 7 中为 ObjC 添加了泛型:
@property NSArray<NSDate *>* dates;
- (NSArray<NSDate *> *)datesBeforeDate:(NSDate *)date;
- (void)addDatesParsedFromTimestamps:(NSArray<NSString *> *)timestamps;
见这里:https: //developer.apple.com/library/prerelease/mac/documentation/Swift/Conceptual/BuildingCocoaApps/WorkingWithCocoaDataTypes.html#//apple_ref/doc/uid/TP40014216-CH6-ID61
回答by Kevin
This was released in Xcode 7(finally!)
这是在 Xcode 7 中发布的(终于!)
Note that in Objective C code, it's just a compile-time check; there will be no run-time error just for putting the wrong type into a collection or assigning to a typed property.
请注意,在 Objective C 代码中,它只是一个编译时检查;不会因为将错误的类型放入集合或分配给类型化的属性而导致运行时错误。
Declare:
宣布:
@interface FooClass <T> : NSObject
@property (nonatomic) T prop;
@end
Use:
用:
FooClass<NSString *> *foo = [[FooClass alloc] init];
NSArray<FooClass<NSString *> *> *fooAry = [NSArray array];
Be careful about those *s.
小心那些*s。
回答by w-m
Generic NSArrays can be realized by subclassing NSArray, and redefining all provided methods with more restrictive ones. For example,
泛型 NSArrays 可以通过子类化来实现NSArray,并用更严格的方法重新定义所有提供的方法。例如,
- (id)objectAtIndex:(NSUInteger)index
would have to be redefined in
必须重新定义
@interface NSStringArray : NSArray
as
作为
- (NSString *)objectAtIndex:(NSUInteger)index
for an NSArray to contain only NSStrings.
使 NSArray 仅包含 NSStrings。
The created subclass can be used as a drop-in replacement and brings many useful features: compiler warnings, property access, better code creation and -completion in Xcode. All these are compile-time features, there is no need to redefine the actual implementation - NSArray's methods can still be used.
创建的子类可以用作替代品并带来许多有用的功能:编译器警告、属性访问、更好的代码创建和 Xcode 中的 -completion。所有这些都是编译时的特性,不需要重新定义实际的实现——NSArray 的方法仍然可以使用。
It's possible to automate this and boil it down to only two statements, which brings it close to languages that support generics. I've created an automation with WMGenericCollection, where templates are provided as C Preprocessor Macros.
可以将其自动化并将其归结为仅两个语句,这使其接近支持泛型的语言。我已经使用WMGenericCollection创建了一个自动化,其中模板作为 C 预处理器宏提供。
After importing the header file containing the macro, you can create a generic NSArray with two statements: one for the interface and one for the implementation. You only need to provide the data type you want to store and names for your subclasses. WMGenericCollection provides such templates for NSArray, NSDictionaryand NSSet, as well as their mutable counterparts.
导入包含宏的头文件后,您可以使用两条语句创建一个通用的 NSArray:一条用于接口,另一条用于实现。您只需要提供要存储的数据类型和子类的名称。WMGenericCollection 为NSArray、NSDictionary和NSSet以及它们的可变对应物提供了这样的模板。
An example: List<int>could be realized by a custom class called NumberArray, which is created with the following statement:
一个例子:List<int>可以通过一个名为 的自定义类来实现,该类NumberArray使用以下语句创建:
WMGENERICARRAY_INTERFACE(NSNumber *, // type of the value class
// generated class names
NumberArray, MutableNumberArray)
Once you've created NumberArray, you can use it everywhere in your project. It lacks the syntax of <int>, but you can choose your own naming scheme to label these as classes as templates.
创建之后NumberArray,您可以在项目中的任何地方使用它。它缺少 的语法<int>,但您可以选择自己的命名方案来将它们标记为类作为模板。
回答by David Jeske
Take a look at:
看一眼:
https://github.com/tomersh/Objective-C-Generics
https://github.com/tomersh/Objective-C-Generics
It appears to be a sort of poor-man's generics, by repurposing the protocol checking mechanism.
通过重新利用协议检查机制,它似乎是一种穷人的泛型。
回答by htzfun
Now dreams come true - there are Generics in Objective-C since today (thanks, WWDC). It's not a joke - on official pageof Swift:
现在梦想成真了——从今天开始,Objective-C 中就有泛型(感谢 WWDC)。这不是开玩笑 - 在Swift 的官方页面上:
New syntax features let you write more expressive code while improving consistency across the language. The SDKs have employed new Objective-C features such as generics and nullability annotation to make Swift code even cleaner and safer. Here is just a sampling of Swift 2.0 enhancements.
新的语法功能可让您编写更具表现力的代码,同时提高整个语言的一致性。SDK 使用了新的 Objective-C 特性,例如泛型和可空性注释,使 Swift 代码更简洁、更安全。这里只是 Swift 2.0 增强功能的一个示例。
And image that proofs this:
以及证明这一点的图像:
回答by drekka
Just want to jump in here. I've written a blog post over hereabout Generics.
只想跳到这里。我在这里写了一篇关于泛型的博客文章。
The thing I want to contribute is that Generics can be added to any class, not just the collection classes as Apple indicates.
我想贡献的是泛型可以添加到任何类,而不仅仅是 Apple 指出的集合类。
I've successfully added then to a variety of classes as they work exactly the same as Apple's collections do. ie. compile time checking, code completion, enabling the removal of casts, etc.
我已经成功地将其添加到各种类中,因为它们的工作方式与 Apple 的集合完全相同。IE。编译时检查、代码完成、启用强制转换等。
Enjoy.
享受。

