Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extension of protocol with method which adds default parameter

I'm used to having default parameters inside protocols using extensions, as protocol declarations themselves can't have them, like this:

protocol Controller {
   func fetch(forPredicate predicate: NSPredicate?)
}

extension Controller {
   func fetch(forPredicate predicate: NSPredicate? = nil) {
      return fetch(forPredicate: nil)
   }
}

Worked perfectly for me.

Now I have the next situation, I have one specific protocol for specific kind of controller:

protocol SomeSpecificDatabaseControllerProtocol {
    //...
    func count(forPredicate predicate: NSPredicate?) -> Int
}

And protocol-extension with implementations of default methods for controllers:

protocol DatabaseControllerProtocol {
    associatedtype Entity: NSManagedObject
    func defaultFetchRequest() -> NSFetchRequest<Entity>
    var context: NSManagedObjectContext { get }
}

extension DatabaseControllerProtocol {
    func save() {
        ...
    }

    func get() -> [Entity] {
        ...
    }

    func count(forPredicate predicate: NSPredicate?) -> Int {
        ...
    }

    //.....
}

My issue is when I'm trying to add method with default parameter to the SomeSpecificDatabaseControllerProtocol extension, I'm receiving a compile-time error, that concrete class conforming to SomeSpecificDatabaseControllerProtocol doesn't conform to the protocol (happens only if I extend protocol):

class SomeClassDatabaseController: SomeSpecificDatabaseControllerProtocol, DatabaseControllerProtocol {...}

What am I missing?

like image 392
Vladyslav Zavalykhatko Avatar asked Oct 28 '22 20:10

Vladyslav Zavalykhatko


1 Answers

This is happening because compiler is confuse due to ambiguous functions.

  1. Here SomeClassDatabaseController receiving count() method from two different protocols.

  2. DatabaseControllerProtocol has count(forPredicate) method which always need parameter.

  3. On other hand SomeSpecificDatabaseControllerProtocol have count() method which can have empty parameter.

  4. To solve this either you have to change count method in DatabaseControllerProtocol to this or you have to implement it in SomeClassDatabaseController.

func count(forPredicate predicate: NSPredicate? = nil) -> Int { return 0}

like image 96
Martin Avatar answered Nov 15 '22 07:11

Martin