[翻译]Swift编程语言——枚举
枚举枚举枚举定义了一组通用类型的相互有关系的值,在你的代码中可以使用枚举值做到类型安全。 或者,枚举成员可以被指定任何类型的联合值而且枚举成员的值类型可以各不相同,像其他语言中的union或者variant一样。你可以定义一组关联的成员作为一个枚举的一部分,它们各自的值类型可以各不相同。 Swift中的枚举是第一类型。枚举具有了一些传统上只有类(class)才有的特性,比如计算过的属性(computed properties)提供当前值的附加属性、比如实例方法(nstance methods)提供和枚举值相关的功能。枚举同样可以定义初始化函数,来提供一个成员的初始值;可以被扩展功能;可以遵循协议(protocol)来提供标准功能。 枚举语法使用enum关键字定义枚举,枚举的名字之后是一对花括号,其中是它的内容: ?enum? ?SomeEnumeration? { ? ?// enumeration definition goes here ?} 这里有个例子,定义了罗盘中的4个主要点: ?enum? ?CompassPoint? { ? ?case? ?North ? ?case? ?South ? ?case? ?East ? ?case? ?West ?} 定义在枚举中的值(North,south,East,West)是那个枚举的成员值(或者成员)。case关键字表示一个新的成员被定义了。 多成员值可以在一行定义,它们之间用逗号分隔: enum? ?Planet? { ? ?case? ?Mercury?,?Venus?,?Earth?,?Mars?,?Jupiter?,?Saturn?,?Uranus?,?Neptune ?} 每个枚举都定义了一个新的类型。像Swift中的其他类型一样,他们的名字(比如CompassPoint和Planet)需要首字母大写。使用单数要比复数好,阅读起来更容易: 在Switch语句中匹配枚举类型你可以使用switch语句匹配单个的枚举内容: directionToHead? = .?South ?switch? ?directionToHead? { ?case? .?North?: ? ?println?(?"Lots of planets have a north"?) ?case? .?South?: ? ?println?(?"Watch out for penguins"?) ?case? .?East?: ? ?println?(?"Where the sun rises"?) ?case? .?West?: ? ?println?(?"Where the skies are blue"?) ?} ?// prints "Watch out for penguins" 你可以这样解读上面的代码: ?let? ?somePlanet? = ?Planet?.?Earth ?switch? ?somePlanet? { ?case? .?Earth?: ? ?println?(?"Mostly harmless"?) ?default?: ? ?println?(?"Not a safe place for humans"?) ?} ?// prints "Mostly harmless" 联合数值(Associated Values)上面的内容展示了一个枚举的成员是如何被定义类型和值的。你可以设置一个常量或变量给Planet.Earth,稍后可以检查它的值。然而有时单独给枚举的每个成员存储联合数值更有必要。这使得你可以存储附加的定制信息连同枚举的成员值一起,在使用枚举成员的值的时候同时可以使用这些附加信息。 举个例子,设想一下库存跟踪系统中,跟踪一个货品可以根据两种不同的条码。有些货品贴了1D的UPC-A格式的条码,这种格式使用0到9的数字。每个条码有一个“数字系统”码,跟随一个五位的“制造商码”和一个五位的“产品代码”,其后的是一个“校验”码(为了保证条码被正确的扫描): 另外的货品使用了2D、QR格式的条码,这个格式可以使用任意 ISO 8859-1的字符,最长可以使用2953个字符: 方便起见,在库存追踪系统中,使用包括4个整型的元组存储UPC-A类型的条码,使用一个字符串存储QR类型的条码。 enum? ?Barcode? { ? ?case? ?UPCA?(?Int?,?Int?,?Int?) ? ?case? ?QRCode?(?String?) ?} 上面代码可以这样解读: switch? ?productBarcode? { ?case? .?UPCA?(?let? ?numberSystem?,?let? ?manufacturer?,?let? ?product?,?let? ?check?): ? ?println?(?"UPC-A: ?(?numberSystem?)?,?(?manufacturer?)?,?(?product?)?,?(?check?)?."?) ?case? .?QRCode?(?let? ?productCode?): ? ?println?(?"QR code: ?(?productCode?)?."?) ?} ?// prints "QR code: ABCDEFGHIJKLMNOP." 如果一个枚举成员的所有的联合数值被当作常量(或者变量)解析,你可以在成员的名字前使用let(或者var)标记,这样更加简洁: switch? ?productBarcode? { ?case? ?let? .?UPCA?(?numberSystem?,?manufacturer?,?product?,?check?): ? ?println?(?"UPC-A: ?(?numberSystem?)?,?(?check?)?."?) ?case? ?let? .?QRCode?(?productCode?): ? ?println?(?"QR code: ?(?productCode?)?."?) ?} ?// prints "QR code: ABCDEFGHIJKLMNOP." 原始值(Raw Values)上面条码的例子展示了枚举的成员如何定义不同类型的联合数值。作为联合数值的一个替代,枚举成员可以有一个预先指定的值(叫做raw values),前提是他们的类型一致。 enum? ?ASCIIControlCharacter?: ?Character? { ? ?case? ?Tab? = ?"t" ? ?case? ?LineFeed? = ?"n" ? ?case? ?CarriageReturn? = ?"r" ?} 这里,枚举被叫做ASCIIControlCharacter ,它被定义为字符类型,被赋值为一些ASCII码的控制字符。字符在 Strings and Characters一章有描述。 原始值的类型可以是字符串、字符、整型或者浮点型。在枚举类型 定义中,每个原始值必须保证唯一性。当整数作为原始值时,如果有枚举成员没有给出值,那么就采用自增。 enum? ?Planet?: ?Int? { ? ?case? ?Mercury? = ?1?,?Neptune ?} 自增意味着Planet.Venus的原始值是2,以此类推。 let? ?earthsOrder? = ?Planet?.?Earth?.?rawValue ?// earthsOrder is 3 依据原始值初始化 下面使用天王星(Uranus)的原始值7得到它的引用: let? ?possiblePlanet? = ?Planet?(?rawValue?: ?7?) ?// possiblePlanet is of type Planet? and equals Planet.Uranus 然而并不是所有的整型值都能找到一个匹配的行星。因此,原始值初始化方式始终返回一个枚举成员的可选类型。这个例子中,posssiblePlanet的类型是Planet?或者可选Planet。 如果你尝试根据9去找一个行星,原始值初始化返回的可选Planet的值将是nil: if? ?let? ?somePlanet? = ?Planet?(?rawValue?: ?positionToFind?) { ? ?switch? ?somePlanet? { ? ?case? .?Earth?: ? ?println?(?"Mostly harmless"?) ? ?default?: ? ?println?(?"Not a safe place for humans"?) ? } ?} ?else? { ? ?println?(?"There isn't a planet at position ?(?positionToFind?)?"?) ?} ?// prints "There isn't a planet at position 9" 上面例子使用了可选绑定,试图根据原始值9访问一个行星。语句 if let somplanet=Planet(rawValue:9)创建了一个可选Planet,如果 可选Planet的值可以检索,将会把这个值赋值给somPlanet。这个例子中,根据9得不到可检索的值,所以else分支将会执行。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |