Objective-C 中有强类型集合吗?
我是 Mac/iPhone 编程和 Objective-C 的新手。 在 C# 和 Java 中,我们有“泛型”,即其成员只能是声明的类型的集合类。 例如,在 C#
Dictionary
中只能包含整数键和 MyCustomObject 类型的值。 Objective-C 中是否存在类似的机制?
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#
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
在 Xcode 7 中,Apple 向 Objective-C 引入了“轻量级泛型”。 在 Objective-C 中,如果存在类型不匹配,它们将生成编译器警告。
在 Swift 代码中,它们会产生编译器错误:
轻量级泛型旨在与 NSArray、NSDictionary 和 NSSet 一起使用,但您也可以将它们添加到您自己的类中:
Objective-C 的行为将像以前一样,但会出现编译器警告。
但 Swift 会完全忽略 Generic 信息。 (在 Swift 3+ 中不再如此。)
与 Objective-C API 交互
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.
And in Swift code, they will produce a compiler error:
Lightweight Generics are intended to be used with NSArray, NSDictionary and NSSet, but you can also add them to your own classes:
Objective-C will behave like it did before with compiler warnings.
but Swift will ignore the Generic information completely. (No longer true in Swift 3+.)
Interacting with Objective-C APIs
不,Objective-C 中没有泛型,除非您想在自己的自定义集合类中使用 C++ 模板(我强烈反对)。
Objective-C 具有动态类型功能,这意味着运行时不关心对象的类型,因为所有对象都可以接收消息。 当您将对象添加到内置集合时,它们将被视为
id
类型。 但不用担心,只需像平常一样向这些对象发送消息即可; 它将正常工作(除非集合中的一个或多个对象不响应您发送的消息)。Java 和 C# 等语言需要泛型,因为它们是强大的静态类型语言。 与 Objective-C 的动态类型功能完全不同。
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 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).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 1.4 中编写一些东西时这样做了几次)例如:
或
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.:
or
这是在 Xcode 7 中发布的 (最后!)
请注意,在 Objective C 代码中,这只是编译时检查; 仅将错误的类型放入集合或分配给类型化属性就不会出现运行时错误。
声明:
使用:
小心那些
*
。This was released in Xcode 7 (finally!)
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.
Declare:
Use:
Be careful about those
*
s.Objective-C 中没有泛型。
来自文档
There are no generics in Objective-C.
From the Docs
Apple 在 XCode 7 中向 ObjC 添加了泛型:
请参见此处:
https: //developer.apple.com/library/prerelease/mac/documentation/Swift/Conceptual/BuildingCocoaApps/WorkingWithCocoaDataTypes.html#//apple_ref/doc/uid/TP40014216-CH6-ID61
Apple has added generics to ObjC in XCode 7:
see here:
https://developer.apple.com/library/prerelease/mac/documentation/Swift/Conceptual/BuildingCocoaApps/WorkingWithCocoaDataTypes.html#//apple_ref/doc/uid/TP40014216-CH6-ID61
通用 NSArray 可以通过子类化 NSArray 并用更严格的方法重新定义所有提供的方法来实现。 例如,
必须将
重新定义为
NSArray
仅包含 NSString。 创建的子类可以用作直接替换,并带来许多有用的功能:编译器警告、属性访问、更好的代码创建和 Xcode 中的完成。 所有这些都是编译时功能,无需重新定义实际实现 - NSArray 的方法仍然可以使用。
可以将其自动化并将其简化为仅两个语句,这使其接近支持泛型的语言。 我使用 WMGenericCollection 创建了一个自动化,其中模板作为 C 预处理器宏提供。
导入包含宏的头文件后,您可以创建一个带有两条语句的通用 NSArray:一条用于接口,一条用于实现。 您只需提供要存储的数据类型和子类的名称。 WMGenericCollection 为
NSArray
、NSDictionary
和NSSet
及其可变对应项提供此类模板。示例:
List
可以通过名为NumberArray
的自定义类来实现,该类是使用以下语句创建的:创建
NumberArray
后code>,您可以在项目中的任何地方使用它。 它缺少
的语法,但您可以选择自己的命名方案将它们标记为类和模板。Generic NSArrays can be realized by subclassing
NSArray
, and redefining all provided methods with more restrictive ones. For example,would have to be redefined in
as
for an NSArray to contain only 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.
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.
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
,NSDictionary
andNSSet
, as well as their mutable counterparts.An example:
List<int>
could be realized by a custom class calledNumberArray
, which is created with the following statement: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.看一下:
https://github.com/tomersh/Objective-C-Generics
通过重新调整协议检查机制,它似乎是一种穷人的仿制药。
Take a look at:
https://github.com/tomersh/Objective-C-Generics
It appears to be a sort of poor-man's generics, by repurposing the protocol checking mechanism.
现在梦想成真了——从今天起 Objective-C 中就有了泛型(感谢 WWDC)。
这不是一个笑话 - 在 Swift 的官方页面上:
证明这一点的图像:
Now dreams come true - there are Generics in Objective-C since today (thanks, WWDC).
It's not a joke - on official page of Swift:
And image that proofs this:
只想跳进这里。 我在这里写了一篇关于泛型的博客文章。
我想要贡献的是泛型可以添加到任何类,而不仅仅是苹果指出的集合类。
我已经成功地添加了各种类,因为它们的工作方式与 Apple 的集合完全相同。 IE。 编译时检查、代码完成、启用强制转换等。
享受吧。
Just want to jump in here. I've written a blog post over here about Generics.
The thing I want to contribute is that Generics can be added to any class, not just the collection classes as Apple indicates.
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.
Enjoy.
Apple 和 GNUStep 框架提供的 Collections 类是半通用的,因为它们假设它们是给定的对象,一些是可排序的,一些是响应某些消息的。 对于浮点型、整数型等基元,所有 C 数组结构都完好无损且可以使用,并且有特殊的包装对象供它们在通用集合类(例如 NSNumber)中使用。
此外,Collection 类可以进行子类化(或通过类别进行专门修改)以接受任何类型的对象,但您必须自己编写所有类型处理代码。
消息可以发送到任何对象,但如果不适合该对象,则应返回 null,或者应将消息转发到适当的对象。 真正的类型错误应该在编译时捕获,而不是在运行时捕获。 在运行时它们应该被处理或忽略。
最后,Objc 提供运行时反射工具来处理棘手的情况,并且可以在发送消息或放入不适当的集合之前检查对象的消息响应、特定类型和服务。
请注意,不同的库和框架采用不同的约定来确定它们的对象在发送没有代码响应的消息时的行为方式,因此 RTFM。 除了玩具程序和调试构建之外,大多数程序不应该崩溃,除非它们真的搞砸了并尝试将错误数据写入内存或磁盘,执行非法操作(例如除以零,但您也可以捕获它),或者访问限制系统资源。
Objective-C 的动态性和运行时允许事情优雅地失败,并且应该内置到您的代码中。
(提示)如果您在函数中遇到通用性问题,请尝试一些特殊性。 使用特定类型重写函数,并让运行时在运行时选择(这就是它们被称为选择器的原因!)适当的成员函数。
The Collections classes provided by Apple and GNUStep frameworks are semi-generic in that they assume that they are given objects, some that are sortable and some that respond to certain messages. For primitives like floats, ints, etc, all the C arrays structure is intact and can be used, and there are special wrapper objects for them for use in the general collection classes (eg NSNumber).
In addition, a Collection class may be sub-classed (or specifically modified via categories) to accept objects of any type, but you have to write all the type-handling code yourself.
Messages may be sent to any object but should return null if it is inappropriate for the object, or the message should be forwarded to an appropriate object. True type errors should be caught at compile-time, not at run-time. At run-time they should be handled or ignored.
Finally, Objc provides run-time reflection facilities to handle tricky cases and message response, specific type, and services can be checked on an object before it is sent a message or put into an inappropriate collection.
Beware that disparate libraries and frameworks adopt different conventions as to how their objects behave when sent messages they do not have code responses for, so RTFM. Other than toy programs and debugging builds, most programs should not have to crash unless they really screw up and try to write bad data to memory or disk, perform illegal operations (eg divide by zero, but you can catch that too), or access off-limits system resources.
The dynamism and run-time of Objective-C allows for things to fail gracefully and should be built in to your code.
(HINT) if yo are having trouble with genericity in your functions, try some specificity. Write the functions over with specific types and let the runtime select (thats why they are called selectors!) the appropriate member-function at run-time.