Treehouse Intermediate Course - Part 8 (Generics 6)
So the sixth and final part on generics! It's been tough but I've accepted that it's all part of learning Swift at a deeper level, rather than learning specific code for particular projects! Let's do this!
Start Time - 15:46
So creating a couple of protocols - linked to views and data. By specifying a protocol as the type, we can specify any type that conforms to that protocol.
So errors are coming up. Here's Pasan's code -
Start Time - 15:46
So creating a couple of protocols - linked to views and data. By specifying a protocol as the type, we can specify any type that conforms to that protocol.
So errors are coming up. Here's Pasan's code -
protocol DataProvider {
associatedtype Object
func object(atIndex index: Int) -> Object
}
protocol ConfigurableView {
associatedtype Data
func configure(with data: Data)
}
class ViewController<View: ConfigurableView, DataSource: DataProvider> {
let view: View
let data: DataSource
init(view: View, data: DataSource) {
self.view = view
self.data = data
}
func start() {
let data = data.object(atIndex: 0)
view.configure(with: object)
}
}
OK the point is that the start function doesn't compile. There is other code from Pasan that does work!
struct StringDataProvider: DataProvider {
let data = ["someValue", "anotherValue"]
func object(atIndex index: Int) -> String {
return data[index]
}
}
struct IntView: ConfigurableView {
func configure(with data: Int) {
//
}
}
struct StringView: ConfigurableView {
func configure(with data: String) {
//
}
}
let controller = ViewController(view: IntView(), data: StringDataProvider())
The associated type is key here. The two different types above are defined by their associated events.
When defining generic constraints, if the constraints are protocols with associated types, then you have access to the associated types.
The class has been added to -
class ViewController<View: ConfigurableView, DataSource: DataProvider> where View.Data == DataSource.Object
We are NOT saying that they have to be the same instance but they do need to be the same type - where the == part is.
Now that function that wasn't working will be!
Ah mine doesn't - still an error! This must be do with the Swift language having evolved beyond this code. Nope - scratch that, I did a typo (needed object not data!).
So, again, a lot of this is over my head. But it is all about exposure to this higher level stuff. I am not going to get bogged down too much with it! Final video straight on!
Extending Generic Types
Here we go! So the point of extensions is to add further functionality to a certain type. In the example below (kindly added by another user on Treehouse as Pasan didn't), there is a long winded code about weather....
struct Weather {
let temperature: Double
let humidity: Double
let chanceOfRain: Double
let icon: String
let highTemperature: Double
let lowTemperature: Double
let sunrise: Date
let sunset: Date
}
let current = Weather(temperature: 63, humidity: 0.36, chanceOfRain: 0.04, icon: "Cloudy", highTemperature: 67, lowTemperature: 50, sunrise: Date(), sunset: Date())
protocol PrettyPrintable {
var prettyDescription: String { get }
}
extension Weather: PrettyPrintable {
var prettyDescription: String {
return "Temperature: \(temperature)\nHumidity: \(humidity)\nChance of Rain: \(chanceOfRain)\nIcon: \(icon)\nHigh Temperature: \(highTemperature)\nLow Temperature: \(lowTemperature)\nSunrise Time: \(sunrise)\nSunset Time: \(sunset)"
}
}
let tuesday = Weather(temperature: 63, humidity: 0.36, chanceOfRain: 0.04, icon: "Cloudy", highTemperature: 67, lowTemperature: 50, sunrise: Date(), sunset: Date())
let wednesday = Weather(temperature: 63, humidity: 0.36, chanceOfRain: 0.04, icon: "Cloudy", highTemperature: 67, lowTemperature: 50, sunrise: Date(), sunset: Date())
let thursday = Weather(temperature: 63, humidity: 0.36, chanceOfRain: 0.04, icon: "Cloudy", highTemperature: 67, lowTemperature: 50, sunrise: Date(), sunset: Date())
let week = [current, tuesday, wednesday, thursday]
extension Array where Element: PrettyPrintable {
var prettyDescription: String {
var output = ""
for (index, element) in self.enumerated() {
output += "\n\n*******\n\nIndex: \(index)\n\n\(element.prettyDescription)"
}
return output
}
}
print(week.prettyDescription)
We have here a structure with key properties. Extensions are used various times to add things like the description etc. My question is why keep adding these and not just put them in the original code?
So this is about extending the array type, filtering by prexies, where there is the prefix containing protocol conformance going on....wowzers!
protocol PrefixContaining {
func hasPrefix(_ prefix: String) -> Bool
}
extension String: PrefixContaining {}
// Enter code below
extension Array where Element: PrefixContaining {
func filter(byPrefix prefix: String) -> [Element] {
var newArray: [Element] = []
for item in self {
if item.hasPrefix(prefix) {
newArray.append(item)
}
}
return newArray
}
}
I did it with lots of help! The for and if bits were actually pretty simple. Was expecting it to be much worse!
Finish Time - 16:31 (45 minutes)
So that's generics! Yes I could go back over bits but I honestly don't think it will help. Tomorrow I will begin closures and definitely revisit generics at some point! The issue is that my capacity for understanding them any better is limited. So I'd rather crack on having spent six separate entries on generics! Until tomorrow!
Comments
Post a Comment