如果案件成员的值是"完全成熟的值本身"(苹果文档),它们如何通过带有值名称的点表示法访问?简单的例子:
enum Suit: String {
case clubs, spades, diamonds, hearts
}
var cardInHand = Suit.hearts
print(cardInHand) //prints hearts
我对如何通过枚举名称访问值感到困惑(看起来静态是在幕后实现的)。对我来说Suit.hearts = hearts
意味着名为hearts的成员存储名为hearts的值。在这种情况下,只有一颗心被宣布为案例心。这是否意味着案例的值隐含地设置为声明的值心,或者相反,心脏以防心脏实际上是值但它隐式设置为同名的静态属性?是否心中有价值心灵的价值或名称?它怎么可能同时出现?
答案 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
非常相似。当然不完全一样,但我希望这有助于你理解枚举定义的背景。