For various reasons I'm splitting the codebase for a Swift iOS app into a series of modules, mostly dependent in a fairly linear fashion. The basis of this question is: If I have a class in one module, and then extend it to conform to a protocol in another module, will all objects of that type conform automatically?. Let's call them Module 1 & Module 2 for now.
A consequence of this modularisation that not every cell for a given UITableView class will be declared within that same module. so to allow me to use cells from outwith that module I've declared a series of protocols describing the basic functions of a cell. For example:
In module 1:
public protocol ActionableCell {
func performAction()
}
Which is used by the tableview so every time a cell is selected, if it conforms to ActionableCell
then performAction()
is called on it. This allows the tableview to handle taps on cells it does not know about.
So, in the tableview's class (Module 1):
open class SomeTableView: UITableView {
// Blah
open override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// If the cell is actionable, inform it that it has been selected
if let cell = tableView.cellForRow(at: indexPath) as? ActionableCell {
cell.performAction()
}
}
However, sometimes the cell is declared in Module 1, but the action is not possible without some module further down the chain, so in Module 1 I declare the class:
open class SomeCell: UITableViewCell {
}
Then in module 2 I make that cell conform to ActionableCell
.
extension SomeCell: ActionableCell {
func performAction() {
// Do Stuff
}
}
So, just to clarify:
In the first module: ActionableCell
is declared, SomeTableView
is declared, SomeCell
is declared but does not conform to ActionableCell
.
Then in the second module: SomeCell
is extended to conform to ActionableCell
If both modules are included & built in my project, but Module 2 is not directly imported in the Swift file either in the tableview class (where the cast to ActionableCell
is performed), or where the cell is created, will the cell conform to ActionableCell
anyway, because the extension is part of the project? If not, at what point is it important to import the extension?
I know that accessing the extended properties of SomeCell
is not possible without importing the second module, but this is about whether it can be cast without importing the extension.
In Swift, you can even extend a protocol to provide implementations of its requirements or add additional functionality that conforming types can take advantage of. For more details, see Protocol Extensions. Extensions can add new functionality to a type, but they can't override existing functionality.
Any type that satisfies the requirements of a protocol is said to conform to that protocol. In addition to specifying requirements that conforming types must implement, you can extend a protocol to implement some of these requirements or to implement additional functionality that conforming types can take advantage of.
In Swift, we can add new functionality to existing types. We can achieve this using an extension. Here, we have created an extension of the Temperature class using the extension keyword. Now, inside the extension, we can add new functionality to Temperature .
One protocol can inherit from another in a process known as protocol inheritance. Unlike with classes, you can inherit from multiple protocols at the same time before you add your own customizations on top.
I've realised this didn't receive any answers, and I've been using this method for a while now, so I thought I should post an answer.
It turns out class extensions are global - if one module extends a class, it is extended for every module by the virtue of that module being present. This is independent of whether the second module is imported, only on it being installed.
So, e.g. if Module A contains class Foo
, and Module B extends Foo
to conform to some protocol (e.g. Hashable
). If Module A then checks for Hashable
conformance, it will find that Foo
does indeed conform if and only if Module B is also present.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With