Swift中的可选数组与空数组

Aar*_*sen 33 arrays optional swift

Person在Swift中有一个简单的类,看起来像这样:

class Person {
    var name = "John Doe"
    var age = 18
    var children = [Person]?

    \\ init function goes here, but does not initialize children array
}
Run Code Online (Sandbox Code Playgroud)

children我可以简单地声明它并将其初始化为一个空数组,而不是声明为可选数组:

var children = [Person]()
Run Code Online (Sandbox Code Playgroud)

我想确定哪种方法更好.将数组声明为可选数组意味着它根本不会占用任何内存,而空数组至少为它分配了一些内存,对吗?因此,使用可选数组意味着至少会节省一些内存.我想我的第一个问题是:这里是否真的存在实际的内存节省,或者我对这个错误的假设是什么?

另一方面,如果它是可选的,那么每次我尝试使用它时,我都必须nil在添加或删除对象之前检查它是否存在.因此那里会有一些效率损失(但我想象的并不多).

我有点像可选的方法.并不是每一个Person都会有孩子,所以为什么不让childrennil,直到Person决定安顿下来,养家?

无论如何,我想知道一种方法或另一种方法是否存在任何其他特定的优点或缺点.这是一个反复出现的设计问题.

Nat*_*ook 19

我要从Yordi做出相反的案例 - 一个空阵列就像清楚地说"这个人没有孩子",并且会为你节省大量的麻烦.children.isEmpty对于孩子的存在是一个简单的检查,你将永远不必解开或担心意外nil.

另外,作为一个注释,将某些东西声明为可选并不意味着它占用零空间 - 就是这样的.None情况Optional<Array<Person>>.

  • 完全同意。如果我们*真的*想知道是否有超过 1 个孩子(解包然后检查它是否不为空),使其可选也强制进行两次检查,这会使代码稍微复杂化,但没有真正的好处。我认为空数组很清楚。 (2认同)

Ant*_*nio 15

在空数组或可选项之间进行选择的能力使我们能够应用从语义角度更好地描述数据的能力.

我会选:

  • 如果列表可以为空,则为空数组,但它是瞬态状态,最后应该至少有一个元素.非可选项表明数组不应为空
  • 如果列表在容器实体的整个生命周期中可能为空,则为可选项.作为可选项表明数组可以为空

让我举一些例子:

  • 包含主数据和详细信息的采购订单(每个产品一个详细信息):采购订单可以有0个详细信息,但这是暂时状态,因为购买订单包含0个产品没有意义
  • 有孩子的人:一个人一辈子都没有孩子.它不是一种短暂的状态(尽管也不是永久性的),但是使用一个可选的,很明显,一个人没有孩子是合法的.

请注意,我的观点仅仅是使代码更清晰和自我解释 - 我认为在选择一个选项或另一个选项时,在性能,内存使用等方面没有任何显着差异.

  • 数组中的项目数是子项数。零项目是零孩子。对数组使用nil意味着计数既不为零也不为非零,这几乎是毫无意义的。nil可能唯一有意义的情况是,如果您想将无法计算的数字传递给调用者(未知),这是唯一可能的其他状态。如果已知子代数,则返回子代数,并通过在数组中包含多个子项来返回子代数。 (2认同)

i4n*_*iac 13

有趣的是,我们最近几乎没有就这个同样的问题进行讨论.

有些人认为存在微妙的语义差异.例如,nil一个人没有任何孩子,但那0意味着什么?这是否意味着"有孩子,其中有0个"?就像我说的那样,在代码中使用这个模型时,纯语义"有0个孩子""没有孩子"没什么区别.在那种情况下,为什么不选择更直接和更少的守护 - ? - y方法?

有人建议保留一个nil可能有迹象表明,例如,当从后端获取模型出错时我们得到错误而不是孩子.但我认为模型不应该尝试使用这种类型的语义,nil不应该用作过去某些错误的指示.

我个人认为该模型应该尽可能愚蠢,在这种情况下最愚蠢的选择是空数组.

有一个可选项会让你拖动它?直到天的结束和使用guard let,if let??一遍又一遍.

您必须有额外的解包逻辑才能NSCoding实现,当您在任何视图控制器中显示该模型时,您将不得不做到person.children?.count ?? 0直截了当person.children.count.

所有操作的最终目标是在UI上显示内容.你真的会说吗?

"这个人没有孩子"和"这个人有0个孩子" nil和空阵相应吗?我希望你不会:)

最后一根稻草

最后,这确实是我最强烈的争论

在Cocoa框架中有很多这样的例子:UIViewController :: childViewControllers等等.

即使是纯粹的Swift世界:Dictionary :: keys虽然这可能有点牵强.

为什么人有nil孩子可以,但不是为了SKNode?对我来说,这个比喻是完美的.嘿,即使SKNode是方法名称是children:)

我的观点:必须有一个明显的理由将这些数组保持为可选项,就像一个非常好的数组,否则空数组提供相同的语义而不需要解包.

最后一根稻草

最后,一些参考非常好的文章,每个都

在Natasha的帖子中,您将找到NSHipster博客文章链接,在Swiftification段落中,您可以阅读:

例如,不是将NSArray返回值标记为可为空,而是修改了许多API以返回一个空数组 - 语义上它们具有相同的值(即,没有),但非可选数组更容易使用

  • 对我来说,"nil"是数据库中的null(与java和c#的null相同).这意味着我们不知道这个人是否有孩子.值为0表示我们知道此人没有孩子. (2认同)

Dec*_*nna 5

有时,不存在的东西和空的东西之间会有区别。

假设我们有一个应用程序,用户可以在其中修改电话号码列表,并将所述修改另存为modifiedPhoneNumberList。如果从未发生过修改,则该数组应为nil。如果用户通过删除解析的数字来修改它们,则所有数组均应为空。

空表示将要删除所有现有的电话号码,零表示我们将保留所有现有的电话号码。区别在这里很重要。

当我们无法区分属性为空还是不存在,或者无所谓为空时,那就去吧。如果a Person失去了自己的独生子,我们只需要删除那个孩子并拥有一个空数组,而不必检查countis 是否为1,然后将整个数组设置为nil