如何存储案例成员值?

时间:2017-07-30 01:38:36

标签: swift enums

如果案件成员的值是"完全成熟的值本身"(苹果文档),它们如何通过带有值名称的点表示法访问?简单的例子:

enum Suit: String {
case clubs, spades, diamonds, hearts

}
var cardInHand = Suit.hearts
print(cardInHand) //prints hearts

我对如何通过枚举名称访问值感到困惑(看起来静态是在幕后实现的)。对我来说Suit.hearts = hearts意味着名为hearts的成员存储名为hearts的值。在这种情况下,只有一颗心被宣布为案例心。这是否意味着案例的值隐含地设置为声明的值心,或者相反,心脏以防心脏实际上是值但它隐式设置为同名的静态属性?是否心中有价值心灵的价值或名称?它怎么可能同时出现?

2 个答案:

答案 0 :(得分:0)

与其他语言中的枚举不同,命名标签不会隐式映射到0,1等。枚举成员是它们自己的枚举名称指定类型的值。枚举可以存储任何类型的值,并且每个枚举成员的类型值可以不同。 请参阅this

答案 1 :(得分:0)

似乎您的主要关注点是为什么您可以获得枚举案例的字符串表示。

首先,它不是enum案例的rawValue。您可以通过以下示例看到:

enum SuitSymbol: String {
    //Please use a browser which can show emojis
    case clubs = "♣️", spades = "♠️", diamonds = "♦️", hearts = "❤️"
}
var cardInHandSymbol = SuitSymbol.hearts
print(cardInHandSymbol) //prints hearts, not ❤️
print(cardInHandSymbol.rawValue) //prints ❤️

这种行为的细节会很长,你应该自己检查一下Swift的源代码:

Print.swift OutputStream.swift

很难深入,但你可以看到print使用隐藏函数_getEnumCaseName生成枚举案例的字符串表示。

因此,案例名称是运行时类型信息的一种,因为您可以使用print获取类型名称:

print(Suit.self) //-> Suit

关于在Swift中思考枚举值的一些信息。

要检查存储在变量中的实际内容(字节序列),Data.init(bytes:count:)是一个很好的工具:

var i: Int = 640
print(Data(bytes: &i, count: MemoryLayout<Int>.size) as NSData) //-><80020000 00000000>
//0x0280 is the hexadecimal representation of decimal `1000` and it's stored in little endian order.

让它适用于Swift枚举:

print(MemoryLayout<SuitSymbol>.size) //-> 1

print(Data(bytes: &cardInHandSymbol, count: MemoryLayout<SuitSymbol>.size) as NSData) //-> <03>

cardInHandSymbol = .clubs
print(Data(bytes: &cardInHandSymbol, count: MemoryLayout<SuitSymbol>.size) as NSData) //-> <00>

cardInHandSymbol = .spades
print(Data(bytes: &cardInHandSymbol, count: MemoryLayout<SuitSymbol>.size) as NSData) //-> <01>

cardInHandSymbol = .diamonds
print(Data(bytes: &cardInHandSymbol, count: MemoryLayout<SuitSymbol>.size) as NSData) //-> <02>

似乎Swift仅使用1个字节来存储SuitSymbol的内部值,实际存储的值为0x00,0x01,0x02和0x03,代表.clubs.spades,{{1}分别和.diamonds

使用嵌入在编译运行时中的一些数据和代码,.hearts和案例名称似乎都与内部值相关联。

(Swift团队的内部代表可能会在不久的将来发生变化,直到Swift团队宣布Swift ABI的稳定性。)

要解释rawValue在评论中的含义,以下代码会告诉您比文字更好的内容:

static

struct SuitStruct: RawRepresentable, CustomStringConvertible, CustomDebugStringConvertible { private var __internalValue: UInt8 private init(__internalValue: UInt8) { self.__internalValue = __internalValue } internal static let __caseNames = ["clubs", "spades", "diamonds", "hearts"] internal static let __rawValues = ["♣️", "♠️", "♦️", "❤️"] static let clubs = SuitStruct(__internalValue: 0) static let spades = SuitStruct(__internalValue: 1) static let diamonds = SuitStruct(__internalValue: 2) static let hearts = SuitStruct(__internalValue: 3) var rawValue: String { return SuitStruct.__rawValues[Int(__internalValue)] } init?(rawValue: String) { if let internalValue = SuitStruct.__rawValues.index(of: rawValue) { self.init(__internalValue: UInt8(internalValue)) } else { return nil } } var description: String { return SuitStruct.__caseNames[Int(__internalValue)] } var debugDescription: String { return String(reflecting: SuitStruct.self) + "." + self.description } } 的行为与枚举SuitStruct非常相似。当然不完全一样,但我希望这有助于你理解枚举定义的背景。