Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS Intermediate Swift 2 Extensions and Protocols Method Dispatch in a Protocol Extension

David Keck
David Keck
5,723 Points

Why isn't anotherUser using the PersonType extension fullName function?

I'm having trouble understanding how anotherUser picks which function to use. For some reason anotherUser calls the struct User version of fullName, while using the PersonType extension version of greeting.

protocol PersonType {

    var firstName: String { get }
    var middleName: String? { get }
    var lastName: String { get }

    func fullName() -> String
}


extension PersonType {

    func  fullName() -> String {
        return "\(firstName) \(middleName ?? "") \(lastName)"
    }

    func greeting() -> String {
        return "Hi, " + fullName()
    }
}

struct  User : PersonType {

    let firstName: String
    let middleName: String?
    let lastName: String

    func greeting() -> String{
        return "Hey there, " + fullName()
    }

    func fullName() -> String {
        return "\(lastName), \(firstName)"
    }
}

let someUser = User(firstName: "Pasan", middleName: nil, lastName: "Premaratne")
let anotherUser: PersonType = User(firstName: "Gabriel", middleName: nil, lastName: "Nadel")

someUser.greeting()              // outputs "Hey there, Premaratne, Pasan"
anotherUser.greeting()           // outputs "Hi, Nadel, Gabriel"

Why doesn't anotherUser output "Hi, Gabriel Nadel" ?

2 Answers

David Keck
David Keck
5,723 Points

Wait. I think i've got it.

anotherUser's type is the PersonType protocol, and since protocols are first class citizens in Swift, they can be used as types. So, since the PersonType protocol dictates that anotherUser must conform by having a fullName function, the fullName function that is called by anotherUser is the one defined by the struct User since anotherUser is really a User struct being cast to a PersonType protocol. Since the PersonType protocol does not dictate that anotherUser must have a definition for greeting, anotherUser uses the function declared inside of the PersonType extension, having already forgone the User struct definition of greeting when it was cast from User to PersonType protocol.

Whew. Can someone check me on that?

David Keck
David Keck
5,723 Points

Would anyone like to check my understanding on this one? Please? :)

Boris Likhobabin
Boris Likhobabin
3,581 Points

There is a rule, that Gabe said we should remember so that is my take on it. Try not to apply logic here but just remember:

If inferred type of a class/struct is a protocol type and the original protocol(without extension) defines a particular method, then that method's implementation is taken from a class/struct If it is NOT DEFINED in the original protocol, the implementation of that method is taken from the protocol extension's default implementation. (despite being defined in class/struct)

So in this particular case function fullname() IS defined in original protocol PersonType, therefore by the rule above anotherUser uses the implemetation defined in a struct. i.e. "....... , Premaratne, Pasan" In contrast you see that greeting() method is not defined in the original protocol so by the rule anotherUser implements greetings() from protocol extension i.e. "Hi, ......."