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 () 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 () below!
You can also find further discussion and get answers to your questions over in Language Help.
Agree with a comment or answer? Like () to up-vote the contribution!
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!!!
@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()
}
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!
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).