Search code examples
iosswiftassociated-types

How to share an associatedtype between two protocols?


I need to declare two protocols, they both have associatedtypes:

protocol MyView {
  associatedtype DataType
  associatedtype LayoutType : MyLayout

  var data: DataType { get }
  var layout: LayoutType { get }

  func doLayout()
}

protocol MyLayout {
  associatedtype DataType

  func computeLayout(with data: DataType?)
}

With this current protocol definition, the associatedtype DataType of MyView is not really the same as the one in MyLayout:

extension MyView {
  func doLayout() {
    layout.computeLayout(with: self.data)
                               ^^^^^^^^^
    Cannot convert value of type 'Self.DataType' to expected argument type '_?'
  }
}

The compiler is telling us that the type is not the same.

Is there a way to share an associatedtype between two protocols to fix my issue? Thanks.


Solution

  • The problem is that it's possible for an implementation of MyView to have a LayoutType with a different DataType to its own DataType. Once SE-0142: Permit where clauses to constrain associated types is implemented, you'll just be able to say:

    associatedtype LayoutType : MyLayout where LayoutType.DataType == DataType
    

    in order to enforce that conforming types must have a LayoutType with a matching DataType.

    However, until this happens, the best you're probably going to be able to do is add the constraint to the extension – which will only make the default implementation of doLayout() available if the DataTypes match.

    extension MyView where LayoutType.DataType == DataType {
        func doLayout() {
            layout.computeLayout(with: data)
        }
    }