Optional в Swift — это не магия языка, а специальный generic-тип, реализованный как enum с двумя кейсами:
public enum Optional<Wrapped> {
case none
case some(Wrapped)
}
Объявление Optional:
var optionalString: String? = "Hello"
// Компилятор преобразует это в:
var optionalString: Optional<String> = .some("Hello")
nil значение:
var noString: String? = nil
// Преобразуется в:
var noString: Optional<String> = .none
Swift предоставляет несколько удобных способов работы с Optional:
?
для объявления??
, !
, ?
и другиеif let
, guard let
)Optional добавляет всего 1 байт к исходному типу:
Int?
: 9 байт (8 для Int + 1 для enum case)Позволяет инициализировать Optional значением nil:
extension Optional: ExpressibleByNilLiteral {
public init(nilLiteral: ()) {
self = .none
}
}
Optional содержит несколько полезных методов:
func map<U>(_ transform: (Wrapped) -> U) -> U?
func flatMap<U>(_ transform: (Wrapped) -> U?) -> U?
Пример:
let number: Int? = 2
let squared = number.map { $0 * $0 } // Optional(4)
var optionalValue: String? = "text"
optionalValue.unsafelyUnwrapped // Аналог force unwrap (!)
Конструкции if let
и guard let
работают через pattern matching:
if case .some(let value) = optionalValue {
print(value)
}
// Эквивалентно:
if let value = optionalValue {
print(value)
}
Вот как можно реализовать упрощенную версию Optional:
enum MyOptional<Wrapped> {
case none
case some(Wrapped)
init(_ value: Wrapped) {
self = .some(value)
}
func map<U>(_ transform: (Wrapped) -> U) -> MyOptional<U> {
switch self {
case .some(let value):
return .some(transform(value))
case .none:
return .none
}
}
}
.none
и .some(Wrapped)
.none
caseПонимание внутренней реализации Optional помогает писать более эффективный и безопасный Swift-код.