Hi everyone!
I have been several days trying to make some refactoring in my code and after many attempts I think that swift is just incapable of achieving what I want to do, here is my scenario:
The scenario
Imagine you have a framework for basic filtering. This filter looks something like this:
protocol Filtrable
{
associatedtype FiltrableItem
associatedtype NewFiltrable : FiltrableDelegate where NewFiltrable.FiltrableItem == FiltrableItem
func isItemValid(transaction: FiltrableItem) -> Bool
func filterByNegatingFilter() -> NewFiltrable
}
The framework should include some default auxiliary filters such as "NotFilter", "AndFilter" etc.
Now here is the problem, there is not a current way in Swift to explicitly specify the types of my filters, so I cannot do things like creating an array of Filtrables.
The current workaround
The only possible workaround that I found so far is to create a base class that defines the protocol associated types and create a stub implementation, then I would make each filter inherit from that class. That way I can now create arrays of that base class, but there is a fundamental problem here: I lost the compiler check for conformance of the protocol
As the base type has to implement the protocol, now the child classes don't have to. This can lead to really easy to make mistakes and a lot of testing infra is required just to validate that does not happen. (not to mention that it makes code less maintainable)
My proposing solutions
- Allow defining types that specify the protocol associated types
This would be the simplest as now I could do something like:
typealias MyAppSpecificFilter = Filtrable where FiltrableItem = MyAppSpecificType, NewFiltrable = MyAppSpecificFilter
The compiler should be happy because it knows exactly the type its dealing with and now I can have true polymorphism and compiler checks across the apps that use my framework
- Allow required to be used in functions
In this scenario I could add "required" to any function in my class and then all subclasses must implement that function too.
The differences between initialization and this scenario would be that methods would not necessarily need to call the super class implementation. This solution would also give kind of the abstract class experience.
Another consideration in this scenario would be that a subclass could use override inside of required and then its subclasses would not be mandated to override the implementation.
The ask
I am asking for feedback regarding this proposals, or if I am missing anything that would make this impossible. I would also love to hear if you have found a better solution than mine to solve this problem.
Thanks for taking the time of reading this!