0

I want to create an extension in swift to an Array where the Element if of ObjectWithGenerics whose Generic conforms to a protocol so that no matter what object I create and have in an array as long as it conforms to my protocol and is of type ObjectWithGenerics I will have access to the methods and computed properties in the extension.

Here is what I tried.

protocol MyProtocol {}

struct ObjectWithGenerics<T> {
    var value: T
}

extension Array where Element == ObjectWithGenerics<MyProtocol> {
    func test() {
        print("It worked")
    }
}

let arr = [Object.ObjectWithGenerics<MyProtocol>]()
// This works but I'm going to be limited to making sure all my arrays are MyProtocols...
arr.test()

struct ConformingObject: MyProtocol {}

// This won't work if I need a specific array of objects like so...
let array = [Object.ObjectWithGenerics<ConformingObject>]()

// This object will not have access to the method `test()` which is the behavior I'm trying to fix
// This object should have access to the `test()` method
array.test()

1 Answers1

0

This is not currently possible in Swift. See the future directions section of SE-0361 for some discussion of how it might be made possible in the future.

Currently you'll have to do something along these lines:

protocol MyProtocol {}

struct ObjectWithGenerics<T> {
    var value: T
}

// Make ObjectWithGenerics implement MyProtocol where appropriate
extension ObjectWithGenerics: MyProtocol where T: MyProtocol {}

// You could also use `extension Collection` here in most cases
extension Array where Element: MyProtocol {
    func test() {
        print("It worked")
    }
}

struct ConformingObject: MyProtocol {}

let array = [ObjectWithGenerics<ConformingObject>]()

array.test()

Or if ObjectWithGenerics can't directly conform to MyProtocol, you can hoist it all with a second protocol:

// Create a new protocol for ObjectWithGenerics when the Element is MyProtocol
protocol ObjectWithGenericsElement {}

extension ObjectWithGenerics: ObjectWithGenericsElement where T: MyProtocol {}

extension Array where Element: ObjectWithGenericsElement {
    func test() {
        print("It worked")
    }
}
Rob Napier
  • 286,113
  • 34
  • 456
  • 610