Inicializadores que Podem Falhar
Parte da seção Programação Orientada a Objetos do Journey de Swift da Coddy. Lição 20 de 57.
Alguns valores não podem ser construídos a partir de qualquer entrada. Um inicializador que pode falhar, escrito como init?, retorna nil em vez de uma instância quando a entrada é inválida, portanto nenhuma instância inválida pode existir:
struct Percentage {
let value: Int
init?(_ value: Int) {
guard value >= 0, value <= 100 else { return nil }
self.value = value
}
}
print(Percentage(42)?.value ?? -1)
print(Percentage(150)?.value ?? -1)Saída:
42
-1O resultado de um inicializador que pode falhar é um opcional, portanto o chamador precisa desembrulhá-lo, geralmente com if let ou guard let:
struct Email {
let address: String
init?(_ text: String) {
let parts = text.split(separator: "@")
guard parts.count == 2, parts[1].contains(".") else { return nil }
address = text.lowercased()
}
}
for text in ["Ada@Mail.com", "not-an-email"] {
if let email = Email(text) {
print("valid: \(email.address)")
} else {
print("invalid: \(text)")
}
}Saída:
valid: ada@mail.com
invalid: not-an-emailOs próprios tipos do Swift usam a mesma ideia: Int("42") e Double("x") são inicializadores falíveis, assim como o init(rawValue:) de um enum. Um inicializador falível pode chamá-los e repassar a falha:
struct Coordinate {
let lat: Double
let lon: Double
init?(text: String) {
let parts = text.split(separator: ",")
guard parts.count == 2,
let lat = Double(parts[0]), let lon = Double(parts[1]),
abs(lat) <= 90, abs(lon) <= 180 else { return nil }
self.lat = lat
self.lon = lon
}
}
print(Coordinate(text: "51.5,-0.1") != nil)
print(Coordinate(text: "95,10") != nil)Saída:
true
falseUse init? quando um valor ausente for informação suficiente. Use um inicializador que lança erros, init(...) throws, quando o chamador precisar saber qual regra falhou:
struct Username {
let text: String
init(_ text: String) throws {
guard text.count >= 3 else { throw NameError.tooShort }
guard text.allSatisfy({ $0.isLetter }) else { throw NameError.badCharacters }
self.text = text
}
}Desafio
FácilComplete a struct Rgb, que armazena uma cor como red, green e blue de 0 a 255. Seu inicializador que pode falhar init?(hex:) lê textos como #FF8000: ele retorna nil, a menos que o texto seja # seguido exatamente por seis dígitos hexadecimais. Use Int(text, radix: 16) para cada par. Adicione uma label calculada que retorne rgb(255, 128, 0).
O código fornecido lê uma cor por linha e imprime o rótulo ou invalid: text.
Seu código deve estar em Rgb.swift. main.swift contém o código fornecido de entrada/saída e não pode ser editado.
Experimente você mesmo
// Código de entrada/saída fornecido: mantenha-o como está
var input: [String] = []
while let line = readLine() { input.append(line) }
for line in input {
if let color = Rgb(hex: line) {
print(color.label)
} else {
print("invalid: \(line)")
}
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Classes e Objetos
Trabalhando com ArquivosDefinindo ClassesMétodos e selfInicializadoresClasses são ReferênciasRevisão - Cartão da Biblioteca4Encapsulamento
Controle de AcessoSomente Leitura ExternaProtegendo o EstadoInicializadores que Podem FalharRevisão - Conta Bancária7Polimorfismo e Genéricos
PolimorfismoConversão de TiposFunções GenéricasTipos GenéricosRevisão - Calculadora de Formas2Structs e Tipos de Valor
StructsSemântica de ValorMétodos MutáveisStruct ou ClasseRecapitulação - Item de Inventário5Herança
SubclassesSobrescrita de métodosInicializadores e superfinal e hierarquiasRecapitulação - Hierarquia de funcionários8Protocolos Padrão
CustomStringConvertibleEquatableComparableHashableRecapitulação - Ordenação Personalizada11Projeto: Gerenciamento de Biblioteca
Livros e MembrosEmpréstimo de LivrosPratique por conta própria: Playground de Swift