After searching, I found this information about your question (please correct me if I am mistaken somewhere or if I miss something):
Even if your code should work logically, the fast compiler does not separate cases when you use regular or readable protocol variables when declaring their type in the MyRepository class. In other words, a bug in the code becomes apparent if you write in the Repository
var secondDataSource: DataSource { get set }
and the compiler does not separate this case. I have not found the absolutely correct way to do what you want. But there are two close ways:
1) The obvious and probably the most correct way is to change the secondDataSource type in MyRepository and use an additional variable if you want:
var _secondDataSource: MyDataSource var secondDataSource: DataSource { get {return _secondDataSource} set { guard let newValue = newValue as? MyDataSource else { fatalError("MyRepository: attempt to set DataSource type, MyDataSource type expected") } _secondDataSource = newValue } }
2) Associated type by protocol. Here I will improve @RaduNunu's answer, since the string associatedtype type = DataSource in its code only has a placeholder effect, and its solution allows you to select any type of secondDataSource ever, String , for example:
protocol Repository { associatedtype Type = DataSource var firstDataSource: DataSource { get } var secondDataSource: Type { get } } struct MyRepository: Repository { var firstDataSource: DataSource var secondDataSource: String
This code will compile and work, but it looks pretty bad. Instead, enter a placeholder that uses the protocol better:
protocol Repository { associatedtype Type: DataSource var firstDataSource: DataSource { get } var secondDataSource: Type { get } } struct MyRepository: Repository { var firstDataSource: DataSource
This code is already pretty close to the goal. However, from now on, you cannot use the protocol as a related type, so the declaration
var secondDataSource: DataSource
MyRepository will not work. This is a fee for using the associated type: you can only use the DataSource corresponding class types / enum / struct.