Home > Back-end >  Extending structs with protocols in Swift
Extending structs with protocols in Swift

Time:11-11

I have the following piece of code. The protocols and extensions I've added don't seem to be doing quite what I expect. What am I missing?

struct foo {
  var getFoo: String
  var getBar: bar
  
  struct bar {
    var getBar: String
  }
}

protocol FooProtocol {
  var getFoo: String { get }
  var getBar: BarProtocol { get }
}

extension foo: FooProtocol {} // Type 'foo' does not conform to protocol 'FooProtocol'

protocol BarProtocol {
  var getBar: String { get }
}

extension foo.bar: BarProtocol {}

The problem in this code is the line extension foo: FooProtocol {}, where we're trying to say that, in effect foo.getBar.getBar should be a valid property. However, Xcode throws up a compilation error saying "Type 'foo' does not conform to protocol 'FooProtocol'.

I can fix this by changing the following:

protocol FooProtocol {
  var getFoo: String { get }
  var getBar: foo.bar { get } // instead of var getBar: BarProtocol { get }
}

However, it seems the line extension foo.bar: BarProtocol {} should mean FooProtocol doesn't care if we give it foo.bar or BarProtocol. What am I missing here?

@Drobs answer was correct. Here's a bonus question.

BONUS

Now suppose I need to implement another struct that conforms to FooProtocol. Neither of these approaches work. What's the fix?

struct FooImplementation: FooProtocol { // Type 'FooImplementation' does not conform to protocol 'FooProtocol'
  var getFoo: String
  var getBar: BarProtocol
}

Do I need to use some sort of typealias to achieve this?

CodePudding user response:

You want to use an associatedtype in the protocol. In that case it essentially says give me a type that implements the protocol BarProtocol.

protocol FooProtocol {
    associatedtype BarType: BarProtocol

    var getFoo: String { get }
    var getBar: BarType { get }
}

protocol BarProtocol {
    var getBar: String { get }
}

struct Foo: FooProtocol {
    var getFoo: String
    var getBar: Bar

    struct Bar: BarProtocol {
        var getBar: String
    }
}
  • Related