FAQ: Protocols and Generics - Protocols in the Swift Standard Library

This community-built FAQ covers the “Protocols in the Swift Standard Library” exercise from the lesson “Protocols and Generics”.

Paths and Courses
This exercise can be found in the following Codecademy content:

Learn Intermediate Swift

FAQs on the exercise Protocols in the Swift Standard Library

There are currently no frequently asked questions associated with this exercise – that’s where you come in! You can contribute to this section by offering your own questions, answers, or clarifications on this exercise. Ask or answer a question by clicking reply (reply) below.

If you’ve had an “aha” moment about the concepts, formatting, syntax, or anything else with this exercise, consider sharing those insights! Teaching others and answering their questions is one of the best ways to learn and stay sharp.

Join the Discussion. Help a fellow learner on their journey.

Ask or answer a question about this exercise by clicking reply (reply) below!
You can also find further discussion and get answers to your questions over in Language Help.

Agree with a comment or answer? Like (like) to up-vote the contribution!

Need broader help or resources? Head to Language Help and Tips and Resources. If you are wanting feedback or inspiration for a project, check out Projects.

Looking for motivation to keep learning? Join our wider discussions in Community

Learn more about how to use this guide.

Found a bug? Report it online, or post in Bug Reporting

Have a question about your account or billing? Reach out to our customer support team!

None of the above? Find out where to ask other questions here!

Hello! I am currently on the last project of the intermediate Swift course (Green Thumb) of the chapter on protocols and generics. This is the only project for which there is no sample solution and we are therefor left completely on our own!!! WHERE IS THE SAMPLE SOLUTION!!!

#intermediate #greenthumb #protocols #genericts #sample #solution #swift

6 Likes
// Write your code below 🥔
struct Store: Hashable {
  let name: String
  let products: [String]
}

let jaysPizza = Store(name: "Jay's Pizza", products: ["Pizza", "Soda", "Salad"])

var salesByStore: [Store: Double] = [jaysPizza: 100]

soooooo, what’s next?

A good question, on the face of it.

Yet more evidence of Codecademy’s sloppiness.

FWIW, a Google search bring up these three sites (they aren’t solutions to the problem, but might help):

@benstone91
Hi Ben, is it possible to get a copy of the solution? I’m not understanding why we need to implement a loop in step 10 (see below), and when I try to build the loop, I get an error message.

Step 10:
for placeholder in arrOfPlants {
plant.printGardeningTips()
}

Thank you for your time and help!

Hey there! Here’s our solution to the problem. I’ve also gone ahead and put the solution up on the platform under the last instruction. Let me know if this answers your question or if you have any followup questions!

enum Month {
    case january, february, march, april, may, june, july, august, september, october, november, december  
}

protocol Plantable {
    var plantMonth: Month { get }
    var plantingInstructions: String { get }

    func cupsOfFertilizer(for rowLength: Int, and rowCount: Int) -> Double
}

protocol Waterable {
    var inchesOfWater: Int { get }
    var wateringFrequency: String { get }
    var wateringInstructions: String { get }
}

protocol Harvestable {
    var harvestMonth: Month { get }
    var harvestingInstructions: String { get }
}

protocol Gardenable: Plantable, Waterable, Harvestable {
    func printGardeningTips()
}

extension Gardenable {
    func printGardeningTips() {
        print("Follow these Gardening 101 tips for a bountiful harvest. 1) Make sure you always water your plant the exact amount that it needs. \("harvestingInstructions"). 2) Make sure you know what zone that you're planting in to ensure that the plants you're planting are in their optimal environment.")
    }
}

struct Kale: Gardenable {
    // Plantable Conformance
    var plantMonth: Month = .january
    var plantingInstructions: String {
        "Plant 3 to 5 weeks before the last frost. Kale can be planted in in-ground gardens, raised beds, or containers."
    }

    // Waterable Conformance
    var inchesOfWater = 2
    var wateringFrequency = "weekly"
    func cupsOfFertilizer(for rowLength: Int, and rowCount: Int) -> Double {
        return Double(rowLength) / 25.0 * 1.5
    }
    var wateringInstructions: String {
        "Water in \(inchesOfWater) inches of water \(wateringFrequency)"
    }

    // Harvestable conformance
    var harvestMonth: Month = .february
    var harvestingInstructions: String {
        "Harvest kale in \(harvestMonth)"
    }
}

func printTips<T: Gardenable>(for plants: [T]) {
    for plant in plants {
        plant.printGardeningTips()
    }
}

let veggies = [Kale()]
printTips(for: veggies)

Thank you @benstone91! This is very helpful, particularly for creating the generic fxn. I just tried to create a second struct “Spinach()” that conforms to Gardenable (and copies all the same protocols as Kale). However when I try to include it in the array “veggies” I am getting the error below. It was possible to call “Kale()” twice, is there something additional that I need to do to call two different structs? (Sorry if I’m missing something obvious here!)

Garden.swift:85:15: error: heterogeneous collection literal could only be inferred to ‘[Any]’; add explicit type annotation if this is intentional
let veggies = [Kale(), Spinach()]
^~~~~~~~~~~~~~~~~~~
as [Any]
Garden.swift:86:1: error: protocol type ‘Any’ cannot conform to ‘Gardenable’ because only concrete types can conform to protocols
printTips(for: veggies)
^

Generics are tricky in Swift, there’s a lot of constraints for how to use them. The function that we wrote will work with any array of garndeable things, but they all have to be the same type. If we want to create an array of heterogenous typed items that all conform to Gardenable, then we’ll have to iterate over the array. The following worked for me:

let spinaches: [Spinach] = [Spinach(), Spinach()]
let kales: [Kale] = [Kale(), Kale()]
printTips(for: spinaches)
printTips(for: kales)

let mixedVeggies: [Gardenable] = [Kale(), Spinach()]
for plant in mixedVeggies {
  plant.printGardeningTips()
}

Outputs (after declaring redefining printGardeningTips for each struct to make it more clear):

Spinach tips!
Spinach tips!
Kale tips!
Kale tips!
Kale tips!
Spinach tips!

Oh terrific, thank you so much @benstone91! This is very helpful!!

Sorry, one more question, when I put this in codecademy it worked, but when I just tried to enter it into Xcode I got the “expressions not allowed at top level” error (screen shot attached).


Is there a way to trouble shoot this? Thank you so much!