强类型集合中为 Null?

Null in a strongly typed collection?

提问人:Alexander Abakumov 提问时间:6/3/2017 最后编辑:Alexander Abakumov 更新时间:6/17/2017 访问量:445

问:

我有一个强类型集合:

NSMutableArray<SupportClass *> *_items;

我需要在其中放置一个类似对象的对象。当您需要在 ObjC 中使用非类型化集合时 - 您可以使用 object:null[NSNull null]

[_items replaceObjectAtIndex:index withObject:[NSNull null]];

但是对于键入的那个,我在该行上收到以下警告:

不兼容的指针类型将“NSNull * _Nonnull”发送到 键入“SupportClass * _Nonnull”

我理解为什么在此示例中混合使用类型化集合和对象时会出现警告。[NSNull null]

什么是正确的方法,使强类型集合具有编译时间类型检查,同时能够将类似对象放入其中?null

iOS Objective-C Cocoa-Touch 构建 警告

评论

0赞 Michael 6/3/2017
强类型意味着它只包含指定类型的对象。如果要放入其他对象,则不再强类型化。您可以将其定义为 ,然后警告将消失。那也会更干净。编写是对你的同事(或事后阅读你的代码的人)的承诺,即只将 -objects 放入此集合中。仅此而已。NSMutableArray *NSMutableArray<SupportClass *> *SupportClass *
0赞 Alexander Abakumov 6/3/2017
正如我在问题中提到的,我理解为什么会产生警告。但是我所知道的所有编程语言都允许有一个带有编译时类型检查的类型化集合,同时能够将 null 对象放入其中。所以我只是在寻找一种对 ObjC 做同样事情的方法。
2赞 Paulw11 6/3/2017
您需要创建某种子类。这可能是一个单例(这就是 NSNull 是什么),因此您可以将数组元素与 NullSupportClass 单例进行比较以检查“null”。但是,数组中可能有错误的数据结构。NullSupportClassSupportClass
0赞 Vladimir Vodolazkiy 6/3/2017
您可以在 SupportClass 中创建一些类似谓词的方法,例如 -(BOOL) isEmpty,如果实例未设置任何属性,则返回 YES。
0赞 Michael 6/3/2017
@AlexanderAbakumov:你可能认为你理解了,但编译器不同意你的观点。我同意编译器;)您面临的问题是经典的 XY 问题。

答:

2赞 CRD 6/6/2017 #1

我有一个强类型集合:

NSMutableArray<SupportClass *> *_items;

结合您的两条评论:

但是,我所知道的[大多数]编程语言允许有一个带有编译时类型检查的类型化集合,同时能够将空对象放入其中。所以我只是在寻找一种对 ObjC 做同样事情的方法。

你面临的麻烦是因为你使用了 Objective-C 的最新添加,旨在改进与 Swift 的互通,而 Swift 不允许你以这种方式将 null 混合到你的“强类型集合”中。

Swift 模型一般是用“非 null 引用和可选”模型替换你习惯的“引用或空”模型。在 Swift 中,对的引用是非空的,而类型是 的简写。该类型有两种情况:和 ,Swift 允许您通过比较 来测试。SomeClassTypeSomeClassType?Optional<SomeClassType>Optional.none.some(v).nonenil

这个模型不是斯威夫特发明的,(就像语言的大多数部分一样)它是从其他语言继承而来的,就像许多函数式语言一样,它们是这种标记联合的强用户。

我的问题是:从有经验的 ObjC 开发人员的角度来看,哪一个是处理该问题的首选?

使用 ,正如您尝试的那样。这是 Apple 推荐的方式,也是 存在的理由,但可以追溯到 Apple 推出轻量级泛型以帮助 Obj-C 和 Swift 之间的桥梁之前。NSNullNSNull

如何在后轻量级泛型世界中使用“引用或空”模型?我认为你知道大多数替代方案,它们包括:

  • 不要。要么不要在 Obj-C 中使用强类型集合,要么按照 Swift 模型使用它们。
  • 使用 Swift。如果要在运行时类型上进行静态强类型,请使用基于它的语言。
  • 使用子类。重写每个方法/属性以引发非法使用 null 异常。添加谓词。等。isNull
  • 使用可分辨对象。不喜欢继承,那么只需创建一个类的唯一实例来充当 null 大小写。添加适当的方法/属性来支持它。
  • 在 Obj-C 中构建自己的。Optional
  • 突破纸墙。轻量级泛型确实是标准集合上的薄薄层,如果有必要,只需突破它即可。
  • 等。

没有单一的“正确方法”来解决您的问题。查看您的设计,确定“空引用”模型是否是关键,选择适合您情况的解决方案。

它)