Type Casting
Part of the Object Oriented Programming section of Coddy's Swift journey. Lesson 33 of 57.
is checks whether a value is of a given type, including subclasses and protocol conformances:
class Animal {}
class Dog: Animal {}
class Cat: Animal {}
let pets: [Animal] = [Dog(), Cat(), Dog()]
print(pets.filter { $0 is Dog }.count)
print(pets[1] is Animal)Output:
2
trueas? tries to treat a value as a more specific type. It returns an optional: the value when the cast works, nil otherwise. Combine it with if let to use the specific type's members:
class Animal {}
class Dog: Animal {
func fetch() -> String { "fetching" }
}
class Cat: Animal {}
for pet in [Dog(), Cat()] as [Animal] {
if let dog = pet as? Dog {
print(dog.fetch())
} else {
print("not a dog")
}
}Output:
fetching
not a dogswitch can match on types with case let x as Type, which handles several types in one place:
let values: [Any] = [42, "hello", 3.5, true]
for v in values {
switch v {
case let n as Int: print("int \(n)")
case let s as String: print("text \(s)")
case is Double: print("a double")
default: print("something else")
}
}Output:
int 42
text hello
a double
something elseas! forces the cast and crashes the program when it fails, so use it only when the type is certain. Frequent casting is often a sign that a method belongs in the protocol or superclass instead:
let pet: Animal = Cat()
// let dog = pet as! Dog // crash: Cat is not a Dog
if let dog = pet as? Dog { print(dog) } // safeChallenge
EasyA settings file is read into [String: Any]. Complete describe(_:), which returns one line per key in alphabetical order: volume: number 7, name: text "Ada", dark: switch on/switch off, ratio: decimal 0.5, or x: unknown for any other type. Use a switch with case let ... as patterns.
The supplied code reads lines key=value and stores the value as Int, Double, Bool or String (in that order of attempts, and [String] for values with |), then prints each returned line.
Your code goes in Functions.swift. main.swift holds the supplied input/output code and cannot be edited.
Try it yourself
// Supplied input/output code: keep it as it is
var input: [String] = []
while let line = readLine() { input.append(line) }
var settings: [String: Any] = [:]
for line in input {
let p = line.split(separator: "=", maxSplits: 1).map(String.init)
let raw = p[1]
if let n = Int(raw) { settings[p[0]] = n }
else if let d = Double(raw) { settings[p[0]] = d }
else if let b = Bool(raw) { settings[p[0]] = b }
else if raw.contains("|") { settings[p[0]] = raw.split(separator: "|").map(String.init) }
else { settings[p[0]] = raw }
}
for line in describe(settings) { print(line) }
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Classes and Objects
Working With FilesDefining ClassesMethods and selfInitializersClasses Are ReferencesRecap - Library Card4Encapsulation
Access ControlRead-Only From OutsideGuarding StateFailable InitializersRecap - Bank Account7Polymorphism and Generics
PolymorphismType CastingGeneric FunctionsGeneric TypesRecap - Shape Calculator5Inheritance
SubclassesOverriding MethodsInitializers and superfinal and HierarchiesRecap - Employee Hierarchy11Project: Library Management
Books and MembersBorrowing BooksPractice on your own: Swift playground