After searching I found this information about your question (please, correct me if I wrong somewhere or if I miss something):
Even while logically your code should work, swift compiler don't separate cases when you use regular or read- only protocol variables when you declaring their type in your MyRepository
class. On other words, error in your code become obvious if you will write in Repository
var secondDataSource: DataSource { get set }
and compiler don't separate this case. I did not found fully right way to do what you want. But there is two close ways:
1) Obvious and probably most right way - change secondDataSource
type in MyRepository
, and use additional variable if you wish:
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 in protocol way. Here I will improve @RaduNunu answer, since associatedtype type = DataSource
line in his code have only placeholder effect, and his solution allows you to choose on adoption 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 is ok!
}
This code will compile and work, but it looks pretty bad. Instead type placeholder you better use protocol conformance:
protocol Repository {
associatedtype Type: DataSource
var firstDataSource: DataSource { get }
var secondDataSource: Type { get }
}
struct MyRepository: Repository {
var firstDataSource: DataSource
//var secondDataSource: String - this line not allowed now
var secondDataSource: MyDataSource
}
This code already pretty close to goal. However, from now you can't use a protocol as associated type, so declaration
var secondDataSource: DataSource
in MyRepository
will not work. This is pay for using associated type: you can use only DataSource
conformed class/enum/struct types.