1

This is a very similar question: Calling protocol default implementation from regular method, BUT none of the answers cover the case when inherance plays a role. The answer suggest casting it to the protocol type itself will solve it, but not in this case (Copy paste in playground):

public protocol MyProtocol {
    func sayCheese()
}

public extension MyProtocol {
    func sayHi() {
        print("Hi, I am protocol")
        sayCheese()
    }

    func sayCheese() {
        print("Cheese from protocol")
    }
}

public class MyFirstClass: MyProtocol {
    public func sayCheese() {
        print("Cheese from 1")

        (self as MyProtocol).sayCheese()
    }
}

public class MySecondClass: MyFirstClass {
    override init() {
        super.init()

        sayHi()
    }

    public func sayHi() {
        print("Hi from 2")
        super.sayHi()
    }

    public override func sayCheese() {
        print("Said cheese from 2")
        super.sayCheese()
    }
}

MySecondClass()

It prints the following:

...
Said cheese from 2
Cheese from 1
Said cheese from 2
Cheese from 1
...

In instance of MyFirstClass, how can I call the default implementation of MyProtocol of method sayCheese?

Edit: My usecase is the following: I have a protocol which is adopted by a class, which is subclassed a lot. The protocol has multiple default methods, which can call eachother. Some of the subclasses needs to override the methods, do stuff, and call super.method() (to finally call the default implementation of the protocol, because a superclass may have overriden the protocol default implementation as well). So I really need dynamic dispatching.

J. Doe
  • 12,159
  • 9
  • 60
  • 114

1 Answers1

1

Although protocols support concrete implementations using extension but that defies the concept of a protocol

A protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality.

and it should be avoided as much as possible until you are truly sure this will not be overriden.

Solution 1:

If you have been into a situation mentioned then i would suggest to introduce an intermediary class that does nothing except conforming to that protocol and then inherit subClasses from that class.

public class Intermediary: MyProtocol {}

public class MyFirstClass: Intermediary {
    public func sayCheese() {
        print("Cheese from 1")

        super.sayCheese()
    }
}

public class MySecondClass: MyFirstClass {
    override init() {
        super.init()

        sayHi()
    }

    public func sayHi() {
        print("Hi from 2")
        super.sayHi()
    }

    public override func sayCheese() {
        print("Said cheese from 2")
        super.sayCheese()
    }
}

Now creating object MySecondClass() will print the below output,

Hi from 2
Hi, I am protocol
Cheese from protocol

Solution 2:

As mentioned in the other question, remove sayCheese method from the protocol so your protocol declaration will be empty but sayCheese will stay in the extension and it will break the recursive calls to sayCheese allowing your app to not freeze.

public protocol MyProtocol {}
Kamran
  • 14,987
  • 4
  • 33
  • 51