当我必须在Swift中选择类,结构和枚举时,我应该如何推理?

ABe*_*its 35 swift

由于类,结构和枚举都具有构造函数,属性和计算属性,因此在选择它们时应如何推理?

Yaw*_*war 18

ChristopheD和Jack Wu的答案很好,但我觉得他们没有触及枚举,或者错过了它们的重要性.Swift枚举是(意味着)代数数据类型的完整实现.类和结构传统上用于对面向对象语言中的数据建模,但枚举通常仅限于用作将变量值限制为有限数量的可能性的便捷方式.例如(C++):

enum MaritalStatus { Unmarried, Married, Divorced, WidowedOrWidowered };
MaritalStatus m = Unmarried;
Run Code Online (Sandbox Code Playgroud)

Swift枚举可以做到以上但他们可以做更多.当然,语言指南有一个非常好的条形码建模示例,但我所知道的最好的例子确实是用代数数据类型建模数据的重点是Scott Wlaschin的演示:http://www.slideshare.net/ScottWlaschin/ddd -with-fsharptypesystemlondonndc2013

您可能会从整个演示文稿中受益,但实际上要"获得"所有您需要看到的内容是幻灯片60,其中他展示了如何在典型的业务线应用程序中建模"付款方式".

在演示文稿中的例子是F#中,但F#是不是那个遥远的斯威夫特,你可以在它们之间很容易映射.例如,Swift中的支付方法枚举如下:

enum PaymentMethod {
    case cash // No extra data needed.
    case cheque(Int) // Cheque #.
    case card(CardType, CardNumber) // 2 pieces of extra data.
}
Run Code Online (Sandbox Code Playgroud)

以上几点是每个订单的付款方式只能是上述三种方法中的一种.编译器不允许任何其他内容.这是构建整个类层次结构以模拟这些几乎无关紧要的事情的非常简洁的替代方法.

演示文稿真的从那里开始,最好的部分是Swift可以在数据建模,使用可选类型等方面完成F#所能做的几乎所有事情.


onm*_*133 17

除了关于class,struct和enum的实际用法的建议之外,这里还有一个比较,它澄清了它们之间的Swift Classes,Structs,Enums和Tuples的能力比较

在此输入图像描述

  • **枚举也可以采用方法.**来自Apple文档:"Swift中的枚举本身就是一流的类型.它们采用传统上仅由类支持的许多功能,例如计算属性,以提供有关枚举当前的其他信息value和instance方法提供与枚举所代表的值相关的功能.枚举还可以定义初始化器以提供初始案例值;可以扩展以扩展其功能,超出其原始实现;并且可以符合协议以提供标准功能" (5认同)

rou*_*ter 9

我认为这是一个非常精致的讨论!我喜欢这里表达的想法:http://www.swift-studies.com/blog/2014/7/1/struct-enum-or-class

有很多细节和他们的建议.我在这里复制了他们的摘要,但这是一篇完整的文章

  • 枚举由有限数量的案例之一初始化,完全由其案例定义,并且在实例化时应始终是该案例的有效实例
  • 结构,当没有有效实例的有限数目应被使用(例如枚举例)和结构也并不形成一个对象的完整定义,而是对象的属性
  • 完全限定初级演员在你的对象模型中,它的属性和它的相互作用.


Jac*_*ack 8

对于初学者来说,类是传递引用,而结构是逐个复制的.

enums仍然是一种特殊的类型来指定枚举.它们应该像以前一样使用.

一般来说,Class vs Structs的选择应该与以前没有太大的不同.类仍然适用于较大/复杂的对象,而Structs适用于小型,隔离的模型对象.结构具有协议等事实现在应该只是用于简化代码并使其更有效.

  • "类是按引用传递"否.Swift总是使用未标记为"inout"的参数传递值,就像Java总是按值传递一样.对象(类的实例)不是值,不能"传递"; 相反,您只能通过指向对象的指针来操纵对象.结构是价值观.当参数不是"inout"时,所有类型都按值传递. (3认同)
  • @newacct太棒了!谢谢你的澄清.这并没有改变答案中的任何内容,因为就像你说的那样,对象总是通过复制指针来传递,并且总是"通过引用传递" (2认同)

Chr*_*heD 5

结构具有成员初始化器(类实例不接收默认的成员初始化器)

所有结构都有一个自动生成的成员初始化器,您可以使用该初始化器来初始化新结构实例的成员属性。可以通过名称将新实例的属性的初始值传递给成员初始化器:

let vga = Resolution(width: 640, height: 480)
Run Code Online (Sandbox Code Playgroud)

这是完全合理的,因为它们是值类型(因此是immutable)。

枚举也是值类型。类是引用类型。这里没有真正的惊喜。


小智 5

通常,当您定义的数据相对简单、不需要担心引用或不需要继承其他数据结构的属性和方法时,您会使用结构而不是类。

如果您有初始化后不应更改的数据,我们可以确保在编译时使用结构体。

在您知道对象的身份将很重要的情况下使用类。换句话说,在您希望多个代码区域指向对象的同一个实例的地方使用类。

在您知道对象的值很重要的情况下使用结构。换句话说,结构非常适用于两个不同的代码区域是否引用同一个实例的情况。

如果您需要在程序的各个部分之间共享可变状态,则应使用类。

如果您需要继承或者您知道要传递对对象的引用,请使用类。