What do these two key points mean at the end of Chapter 17, Protocols?

  • If you create an extension on a protocol that isn’t declared in the protocol, conforming types cannot override the extension.
  • If you create an implementation in an extension declared in the protocol, conforming types can override the extension.

Hello,
If you have a function not defined as part of the protocol and is implemented in the protocol extension, any types conforming to this protocol will not be able to override that implementation.
But if that function is indeed part of the protocol definition, you will be able to override it.

That’s related to dynamic dispatch and static dispatch. if you are interested to understand more about it :]

The following code conveys what you mean, right?

protocol Pro {
    func methodInProtocol()
}

extension Pro {
    func methodInProtocol() {
        print("methodInProtocol by extension")
    }

    func methodNotInProtocol() {
        print("methodNotInProtocol by extension")
    }
}

class Foo: Pro {
    func methodInProtocol() {
        print("methodInProtocol by class")
    }

    func methodNotInProtocol() {
        print("methodNotInProtocol by class")
    }
}

let foo = Foo()
foo.methodInProtocol() // methodInProtocol by class
foo.methodNotInProtocol() // methodNotInProtocol by class

let pro: Pro = Foo()
pro.methodInProtocol() // methodInProtocol by class
pro.methodNotInProtocol() // methodNotInProtocol by extension

Exactly yes.
by adding the function to the protocol definition, dynamic dispatch is used. that’s why even when u treat the variable using its protocol type, the function in the class is still being called.
If not added, static dispatch is used and the function specified in the extension will be called and not the class.

1 Like

Thank you for answering my question.

1 Like

Pop quiz… just for fun. :grin: What will the following print?

protocol Drawable {
  func draw()
}

extension Drawable {
    func draw() {
        print("Base draw()")
    }
}

extension Drawable {
   func drawCircle() {
      print("Base drawCircle()")
   }
}

func render(shape: any Drawable) {
  shape.draw()
  shape.drawCircle()
}

struct Square: Drawable {
    func draw() {
        print("Square draw")
    }
    func drawCircle() {
        print("Square drawCircle()")
    }
}

render(shape: Square())
//Square draw
//Base drawCircle()

Verified in Xcode

1 Like

Righteo. :+1: Sorry if that was obvious. :sweat_smile: