Swift Expressible literal
Swift Expressible Literal
引子
從一個面試題說起。有如下代碼:
struct Book {
let name: String
}
let book: Book = "Charlotte's Web"
請問是否可以讓它正常編譯?
字面量
字面量指字面代表的常量值。這樣解釋起來有點像廢話。但是通過例子就很容易理解了。
以下是 Swift 中的一些字面量:
種類 | 示例 |
---|---|
字符串 | "ich" , Bingo! |
浮點型數字 | 1001.3 , 33.0 |
整型數字 | 1001 , 33 |
布爾值 | true , false |
數組 | ["Emily", "Ben", "Eric"] |
字典 | ["name": "Ben"] |
空 | nil |
Expressible Literal 協議
Swift 中,String
, Float
, Double
, Int
和 Bool
等類型,和上面的 Book
一樣,都是 struct 。那麼它們是怎麼實現將字面量直接創建實例的呢?以下是 Bool
類型的一個拓展:
extension Bool : ExpressibleByBooleanLiteral {
/// Creates an instance initialized to the specified Boolean literal.
///
/// Do not call this initializer directly. It is used by the compiler when
/// you use a Boolean literal. Instead, create a new `Bool` instance by
/// using one of the Boolean literals `true` or `false`.
///
/// var printedMessage = false
///
/// if !printedMessage {
/// print("You look nice today!")
/// printedMessage = true
/// }
/// // Prints "You look nice today!"
///
/// In this example, both assignments to the `printedMessage` variable call
/// this Boolean literal initializer behind the scenes.
///
/// - Parameter value: The value of the new instance.
public init(booleanLiteral value: Bool)
/// A type that represents a Boolean literal, such as `Bool`.
public typealias BooleanLiteralType = Bool
}
再看看 Float
的一個拓展:
extension Float : ExpressibleByIntegerLiteral {
/// Creates an instance initialized to the specified integer value.
///
/// Do not call this initializer directly. Instead, initialize a variable or
/// constant using an integer literal. For example:
///
/// let x = 23
///
/// In this example, the assignment to the `x` constant calls this integer
/// literal initializer behind the scenes.
///
/// - Parameter value: The value to create.
public init(integerLiteral value: Int64)
/// A type that represents an integer literal.
///
/// The standard library integer and floating-point types are all valid types
/// for `IntegerLiteralType`.
public typealias IntegerLiteralType = Int64
}
除了 ExpressibleByBooleanLiteral
和 ExpressibleByBooleanLiteral
類似的協議還有 ExpressibleByStringLiteral
, ExpressibleByNilLiteral
, ExpressibleByArrayLiteral
等等。
所以,最開始的那個題目,就有答案了。
注意上面兩個大代碼塊裏面的注釋,都有一句 Do not call this initializer directly
。