Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to override a protocol extension's default implementation of a func?

Tags:

swift

Is it possible to get the following code to make MyClass2:someFuncWithDefaultImplementation() invoked?

protocol MyProtocol : class {
    func someFuncWithDefaultImplementation()
    func someFunc()
    var  someInt:Int { get set }
}

extension MyProtocol {
    func someFuncWithDefaultImplementation() {
        someInt = 5
    }

    func someFunc() {
        someFuncWithDefaultImplementation()
    }
}

class MyClass :  MyProtocol {
    var someInt = 6
}

class MyClass2 : MyClass
{
    func someFuncWithDefaultImplementation()
    {
        someInt = 7
    }
}


...

  let class2 = MyClass2()
  class2.someFunc()

MyClass2 could have this method added:

func someFunc() {
       someFuncWithDefaultImplementation()
}

And it would work, but that is no use if MyProtocol:someFunc() is doing other stuff apart from calling someFuncWithDefaultImplementation() as it would just be code duplication.

Also doing this does not have the desired effect:

extension MyClass2 {
    func someFuncWithDefaultImplementation()
    {
        someInt = 7
    }
}
like image 565
Gruntcakes Avatar asked Apr 05 '17 23:04

Gruntcakes


People also ask

Can we override protocol in Swift?

An extension can't be overridden because the way Swift implement extension is using static dispatch which means its resolved at compile time. Ok, actually above code can be compiled using some tricks if it is your goal to make the code compile.

Can we override extension method Swift?

If a protocol defines a method, and provides a default implementation in an extension, a class can override that method, and the override will be called for any reference to the instance, even if the reference's type is declared as the protocol.

Can we override method in extension?

Extension methods cannot be overridden the way classes and instance methods are. They are overridden by a slight trick in how the compiler selects which extension method to use by using "closeness" of the method to the caller via namespaces.

Is it possible to prevent the adoption of a protocol by a struct?

The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of those requirements. But there would be a time when you want to restrict protocols to be adopted by a specific class. In Swift 5, you can do just that.


1 Answers

The default implementations in the protocols are only called if the class that conforms to these protocols do not implement that method itself. The classes' methods override the default implementations of the protocols, not the other way around.

you could do like this:

import UIKit

protocol MyProtocol : class {
    func someFuncWithDefaultImplementation()
    func someFunc()
    var  someInt:Int { get set }
}

extension MyProtocol {
    func someFuncWithDefaultImplementation() {
        someInt = 5
    }

    func someFunc() {
        someFuncWithDefaultImplementation()
    }
}

class MyClass :  MyProtocol {
    var someInt = 6
}

class MyClass2 : MyProtocol
{
    var someInt: Int = 4
    func someFuncWithDefaultImplementation()
    {
        someInt = 7
    }

}


let class2 = MyClass2()
class2.someFunc()

or like this:

class MyClass :  MyProtocol {
    var someInt = 6
    func someFuncWithDefaultImplementation() {
        someInt = 8
    }
}

class MyClass2 : MyClass
{
    override func someFuncWithDefaultImplementation()
    {
        someInt = 7
    }
}

these were what i got with my tests, but you may find some better solution

like image 71
nsleche Avatar answered Nov 15 '22 09:11

nsleche