UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

How cast class?

Forums > Swift

You're on the right track, but theres a couple of things youve misunderstood here. You're actually passing in the type to describeRun rather than an instance.

func describeRun(runningWorkout: Workout) {
    if let thisShape = runningWorkout as? Run {
        print(thisShape.cadence)
    } else if let ff = runningWorkout as? Workout {
        print("33")
    }
}

let run = Run(cadence: 5, time: 10, distance: 2)
describeRun(runningWorkout: run)

You can only cast specific instances, rather than types.

1      

Im sorry, I dont understand what you're asking. If I copy your code into a playground it works fine.

are you asking how can you adapt your describe to use an array?

if so you can move your for loop into describe(workouts: [Workout]). alternatively, edit your for loop to do this

for workout in workouts {
  describeRun(runningWorkout: workout)
  }

Apologies for the formatting, its difficult to reply on iPad.

1      

Nice! That is a good way to clean up your code.

If you are only interested in runs, you can clean this up even more:

func describeRuns(in workouts: [Workout]) {
    let runs = workouts.compactMap { $0 as? Run }
    for run in runs {
        print("\(run.cadence) \(run.time) \(run.distance)")
    }
}

compactMap there loops through each workout item, and casts to Run. For any Workout instances that arent a Run, then nil is returned. The beauty of using compactMap, is that any nil values are stripped out so you're only left with the things you care about.

Have fun!

1      

Set's require the elements to be Hashable. That error is telling you that the Workout type does not conform to the Hashable protocol. I'd suggest you read up on how to conform to Hashable, theres an article here.

1      

Maybe so....

func describeRun (runningWorkout: Run) {
    print(" \(runningWorkout.cadence), \(runningWorkout.time), \(runningWorkout.distance)")
}

func describeSwim (swimmingWorkout: Swim) {
    print("\(swimmingWorkout.stroke), \(swimmingWorkout.time), \(swimmingWorkout.distance)")
}

for workout in workouts {
    if let workout = workout as? Run {
        describeRun(runningWorkout: workout)
    } else if let workout = workout as? Swim {
        describeSwim(swimmingWorkout: workout)
    }
}

1      

This is not a problem that should be solved with casting or using dictionaries. Instead you should add either method or computed property that will return description string and subclasses of Workout will use the override keyword to customize it.

https://docs.swift.org/swift-book/LanguageGuide/Inheritance.html

2      

Hacking with Swift is sponsored by RevenueCat

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.