אתחולים שעלולים להיכשל
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Swift של Coddy. שיעור 20 מתוך 57.
אי אפשר ליצור ערכים מסוימים מכל קלט. אתחול שניתן לכישלון, שנכתב init?, מחזיר nil במקום מופע כשהקלט אינו תקין, כך שאף מופע לא תקין לא יוכל להתקיים:
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)פלט:
42
-1התוצאה של אתחול שניתן להיכשל בו היא אופציונלית, ולכן הקוד הקורא חייב לחלץ ממנה את הערך, בדרך כלל באמצעות if let או 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)")
}
}פלט:
valid: ada@mail.com
invalid: not-an-emailהטיפוסים המובנים של Swift משתמשים באותו רעיון: Int("42") ו-Double("x") הם אתחולים שעלולים להיכשל, וכך גם init(rawValue:) של enum. אתחול שעלול להיכשל יכול לקרוא להם ולהעביר הלאה את הכישלון:
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)פלט:
true
falseהשתמשו ב־init? כשערך חסר מספיק כמידע. השתמשו במאתחל שזורק שגיאה, init(...) throws, כשהקורא אמור לדעת איזה כלל נכשל:
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
}
}אתגר
קלהשלימו את המבנה Rgb, ששומר צבע בתור red, green ו-blue בטווח שבין 0 ל-255. המאתחל הכושל שלו init?(hex:) קורא טקסט כמו #FF8000: הוא מחזיר nil אלא אם הטקסט הוא # ואחריו בדיוק שש ספרות הקסדצימליות. השתמשו ב-Int(text, radix: 16) עבור כל זוג. הוסיפו את label המחושב, שמחזיר rgb(255, 128, 0).
הקוד שסופק קורא צבע אחד בכל שורה ומדפיס את התווית או את invalid: text.
כתבו את הקוד שלכם ב-Rgb.swift. הקובץ main.swift מכיל את קוד הקלט/פלט שסופק ואי אפשר לערוך אותו.
נסו בעצמכם
// קוד הקלט/פלט שסופק: יש להשאיר אותו כפי שהוא
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)")
}
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
תרגלו בעצמכם: Swift אונליין