Swift Programming Language Reference: Declarations, 코드부분
Swift Programming Language Guide: Failable Initializers, 코드부분
Swift Blog: Failable Initializers, 코드부분
/* Failable Initializers (Language Reference) */
struct SomeStruct {
let property: String
// produces an optional instance of 'SomeStruct'
init?(input: String) {
if input.isEmpty {
// discard 'self' and return 'nil'
return nil
}
property = input
}
}
if let actualInstance = SomeStruct(input: "Hello") {
// do something with the instance of 'SomeStruct'
} else {
// initialization of 'SomeStruct' failed and the initializer returned 'nil'
}
/* Failable Initializers (Language Guide) */
let wholeNumber: Double = 12345.0
let pi = 3.14159
if let valueMaintained = Int(exactly: wholeNumber) {
print("\(wholeNumber) conversion to Int maintains value of \(valueMaintained)")
}
let valueChanged = Int(exactly: pi)
if valueChanged == nil {
print("\(pi) conversion to Int does not maintain value")
}
struct Animal {
let species: String
init?(species: String){
if species.isEmpty { return nil }
self.species = species
}
}
let someCreature = Animal(species: "Giraffe")
if let giraffe = someCreature {
print("An animal was initialized with a species of \(giraffe.species)")
}
let anonymousCreature = Animal(species: "")
if anonymousCreature == nil {
print("The anonymous creature could not be initialized")
}
// Failable Initializers for Enumerations
enum TemperatureUnit {
case kelvin, celsius, fahrenheit
init?(symbol: Character) {
switch symbol {
case "K":
self = .kelvin
case "C":
self = .celsius
case "F":
self = .fahrenheit
default:
return nil
}
}
}
let fahrenheitUnit = TemperatureUnit(symbol: "F")
if fahrenheitUnit != nil {
print("This is a defined temperature unit, so initialization succeeded.")
}
let unknownUnit = TemperatureUnit(symbol: "X")
if unknownUnit == nil {
print("This is not a defined temperature unit, so initialization failed.")
}
// Failable Initializers for Enumerations with Raw Values
enum TemperatureUnit: Character {
case kelvin = "K", celsius = "C", fahrenheit = "F"
}
let fahrenheitUnit = TemperatureUnit(rawValue: "F")
if fahrenheitUnit != nil {
print("This is a defined temperature unit, so initializaion succeeded.")
}
let unknownUnit = TemperatureUnit(rawValue: "X")
if unknownUnit == nil {
print("This is not a defined temperature unit, so initialization failed.")
}
// Propagation of Initialization Failure
class Product {
let name: String
init?(name: String){
if name.isEmpty { return nil }
self.name = name
}
}
class CarItem: Product {
let quantity: Int
init?(name: String, quantity: Int){
if quantity < 1 { return nil }
self.quantity = quantity
super.init(name: name)
}
}
if let twoSocks = CarItem(name: "sock", quantity: 2) {
print("Item: \(twoSocks.name), quantity: \(twoSocks.quantity)")
}
if let zeroShirts = CarItem(name: "shirt", quantity: 0) {
print("Item: \(zeroShirts.name), quantity: \(zeroShirts.quantity)")
} else {
print("Unable to initialize zero shirts")
}
if let oneUnnamed = CarItem(name: "", quantity: 1) {
print("Item: \(oneUnnamed.name), quantity: \(oneUnnamed.quantity)")
} else {
print("Unable to initialize one unnamed product")
}
// Overriding a Failable Initializer
// Note: You can override a failable initializer with a nonfailable initializer but not the other way around.
class Document {
var name: String?
init() {}
init?(name: String) {
if name.isEmpty { return nil }
self.name = name
}
}
class AutomaticallyNamedDocumnet: Document {
override init() {
super.init()
self.name = "[Untitled]"
}
override init(name: String) {
super.init()
if name.isEmpty {
self.name = "[Untitled]"
} else {
self.name = name
}
}
}
class UntitledDocument: Document {
override init() {
super.init(name: "[Untitled]")!
}
}
/* Failable Initializers (Swiff Blog) */
if let image = NSImage(contentsOfFile: "swift.png") {
// loaded the image successfully
} else {
// could not load the image
}
extension Int {
init?(fromString: String){
if let i = Int(fromString) {
self = i
} else {
return nil
}
}
}
enum Color: Int {
case Red = 0, Green = 1, Blue = 2
init?(rawValue: Int){
switch rawValue {
case 0:
self = .Red
case 1:
self = .Green
case 2:
self = .Blue
default:
return nil
}
}
}