I've found a tricky situation and I can't see an elegant way to solve it. Basically, I have a protocol with multiple functions. Then I have multiple implementations, and I would like to have an object that implements the protocol by choosing one of these implementations depending on the function to call:
The problem with this is that it's mostly boilerplate code. The functions are just redirecting to another object which implements the protocol, without touching the parameters. If I need to change a function type, I need to change this redirection too. This is what I would like to do:
This related to OO Patterns like Strategy, Factory, Facade, and AbstractFactory: polymorphism... I think implementing it would go better with classes rather than structs.
I believe the issue you have here is the fact that functions can't be assigned. However, you may be able to get away with computed instance variables which can be:
protocol DataSource {
var loadUsers: (String) -> Users { get }
var loadData: (String) -> Data { get }
}
struct NetworkDataSource: DataSource {
var loadUsers: (String) -> Users = … // Network call
var loadData: (String) -> Data = … // Network call
}
struct StaticDataSource: DataSource {
var loadUsers: (String) -> Users = … // Return static data
var loadData: (String) -> Data = … // Return static data
}
struct AppDataSource: DataSource {
var loadUsers: (String) -> Users = NetworkDataSource().loadUsers // Call NetworkDataSource
var loadData: (String) -> Data = StaticDataSource().loadData // Call StaticDataSource
}
Unfortunately, you'd need to drop the argument labels in this case.
Yes, that is the closest solution I have found, but loosing argument labels is kind of a dealbreaker here. I'm not sure why we can't have argument labels with functions as variables.
That is still waiting for the Core team to comment on their announcement that labels would be back someday as the issue gets reconsidered. I think it was really bad jay we lost argument labels in closures and functions stored on variables...
I've since relaxed my stance on argument labels, and I'm using now the "struct with functions as properties" approach. It gives a lot of flexibility. Also, argument labels can be added if really needed by adding a function to the struct that just calls the corresponding stored function.