Treehouse Intermediate Course - Part 5 (Generics 3)

So to save the strain on my eyes, I am going to do several shorter entries today but put them into this one blog. It seems silly to have shorter entries which are all about the same content! Last time, generics was tough. But it was useful stuff! The challenge was tricky and so was the content; I'm going to continue with the current course, then do extra reading wherever necessary.

Start Time - 09:55

Class Based Type Constraints

So Pasan states that the example is 'trivial'...doesn't bode well!

class Shape {}
    
    func centre<T: Shape>(of shape: T) {
     print("Called")
    }


let testShape = Shape()


centre(of: testShape)

So just an example here of creating a class and then declaring the type within the <T: Shape> bit. 

It works with inheritance too - if I created a subclass of Shape it would work. 

func centreOf(_ shape: Shape) {
    print("Centre")
}
 centre(of: testShape)

This means that the Shape type still needs the <T> type when the function is called. 


OK, breaking it down. The base class and generic bit is fine. Arguments and return type all OK. 
The next bit looks hard but let's give it a go!

func largest<T>(in: [T]) -> T? {
    
}

That's the main syntax. The array bit...not sure yet. Comparable needs to be put in. Let's do that.

    var max: T?
    
    for item in array {
        if item > max {
            max = item
  
I know we're missing some brackets, but this still doesn't work. I need some help...just a clue!

OK I'm glad I looked as I would never have got this!

func largest<T: Comparable>(in array: [T]) -> T? {
    
    
    let result = array.max()
    
    return result
}

That's based on someone using the max property; they actually did the $0 > $1 comparison but I didn't seem to need to. I'll see if it works first...Yes!

Something I did do well was create an external parameter name - no instruction to do so but I did this intuitively. It meant that the code of finding the max of the array made more sense. 

Have to pause it there but back soon!

Paused at 10:17 (22 minutes so far)

*Continued at 13:30

Here we go - part 2 for the day!

So before continuing, I want to review the content from this section on generics. The first few lessons were fine but it suddenly got harder with multiple parameters. Let's go over some of that before moving on!

Multiple Type Parameters

I think what was tricky with this was that the example was pointless. Doing intToString or stringToInt can be done anyway. So it was kind diffuse. 

Right so the concept here is taking another function to be used as an argument. 

func change<T, U>(arg: T, operation: (T) -> U) -> U {
    
}

So before I found the whole operation bit confusing. Now it makes more sense. We are putting a function within this argument! The T needs to be in brackets like (T) because that is the function input. And that function will be outputting the type U, which is why we have <T, U> to start with. OK. 

So putting in a function as a parameter/argument label. Got that. 

func change<T, U>(arg: T, operation: (T) -> U) -> U {
    return operation(arg)
}

func stringToInt(_ a: String) -> Int {
    guard let value = Int(a) else {
        fatalError() }
    return value
}

change(arg: "1", operation: stringToInt)


The return bit in change is very general (pun intended!) at the moment. The stringToInt is a custom made method, which is then passed into the use of the change function. So to use the change function, you basically need a method that follows the same protocol. In this case that is one type (T) changing to another (U).

func intToString(_ a : Int) -> String {
    return String(a)
}

So why is that function so much simpler? Let's have a look...

Ok the reason is that you can always convert to a String ANY integer. So that's why! For String to int, you have to do the guard let, as the value may have been e.g. "Cath", and that CAN'T be converted to an integer. Whereas for the other way round, ANY integer can be converted to a string. Cool!

change(arg: 44, operation: intToString)

I'm glad I went over that - makes more sense now!

Protocol Based Type Constraints

Last bit of recap before next course. So with this, the key bit is you use an actual protocol. The other difference with the code used, is that Pasan uses 'sensible names' e.g. for the dictionary/key one, he uses key and value. 

The above does NOT work. Why? At the moment they cannot be compared. Equatable is the protocol that has to be applied. Any type that is substituted for the value-type parameter, has to conform to that protocol. That is not clear to me. 

*Paused for 5 minutes

Extra Reading

Right, so a bit clearer. As the types are generic, they do not automatically allow you to use the == or != operands. This is the same for custom types! So if a class/struct has properties, you cannot actually compare them with the == unless the right protocol is used. That is a type of behaviour. Cool!
(all from the Swift Dev website).

*Paused for 12 minutes

OK, last bit for today!

Generics Types in the Standard Library

Another way to create an array - 

var numbers = Array<Int>()

The point is that Array is a type. There is in-built code for this on Swift. 

let city = "Winchester"

let streetName = Optional.some("Winchester")

Again, under the hood there is more going on. Looking at the info in the standard library, you could use none as a case. Optional is apparently a public enum! I did some extra work on this before - dictionary is a generic type as it can take in multiple types. 

var errorCodes = Dictionary<Int, String>()

I have to stop there! So not a huge amount achieved, but little by little remember! I'm not going to be able to code again until Monday, at the earliest. Unless I can sneak in an entry here or there during a busy time. But if I can't, no problem. All good, steady progress either way!

Finish Time - 14:32 (1 hour 7 minutes today)

Next time, I'm going to continue with generics, with the aim to complete those within two entries. 

Comments

Popular posts from this blog

*Xcode Project Entry 2* F1 Quiz - part 1

Angela Yu Course Part 10 (up to lesson 112)

Angela Yu Xcode 12 Course - Part 7 (lectures 74 to 79)