Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extend a Protocol with Multiple Constraints for One OR the Other - Swift

I want to extend protocol with a default implementation that satisfies OR ( || ) constraint.

class A { }
class B { }

protocol SomeProtocol { }

/// It will throw error for || 
extension SomeProtocol where Self: A || Self: B { 
}
like image 240
salman siddiqui Avatar asked Jul 03 '18 08:07

salman siddiqui


1 Answers

You can't extend a protocol with OR as you can't do it in a if let, because with this the compiler infers the type of self or of the var, so if it conforms 2 types, the compiler doesn't know of what type is self.

(When you type self. or any var. the compiler always knows what type of var is in compiler type, in that case it would be in runtime). So the easiest way is to make that the 2 types conforms a protocol and do a extension of that protocol. So the compiler knows that self conforms a protocol and he doesn't care of the exact type of Self (But you will be able to use only the properties declared in the protocol).

protocol ABType {
// Properties that you want to use in your extension.
} 

class A: ABType, SomeProtocol { }
class B: ABType, SomeProtocol { }

protocol SomeProtocol { }

extension SomeProtocol where Self: ABType { 
}

Also if you want to apply the extension to both types you have to do it one by one.

extension A: SomeProtocol { }
extension B: SomeProtocol { }

// Silly example: (In this case is not really useful, but it is just to show how to make to make 2 classes conforms a protocol and to make a extension of it using a method declared in that protocol and creating a default implementation.)

protocol ABType {
    func getName()
}

class AClass: ABType {
    func getName() {
        print ("A Class")
    }
}

class BClass: ABType, someProtocol {
    func getName()  {
        print ("B Class")
    }
}

protocol someProtocol {
    func anotherFunc()
}

extension someProtocol where Self: ABType {
    func anotherFunc() {
        self.getName()
    }
}

let a = AClass()
// a.anotherFunc() <- Error, A cant call anotherFunc
let b = BClass()
b.anotherFunc()
like image 67
Pablo Sanchez Gomez Avatar answered Oct 06 '22 02:10

Pablo Sanchez Gomez