Is it possible to provide an extension that only adds functionality to classes conforming to a protocol? The functionality I'm trying to achieve is something like this:
protocol Identifiable {
var id: String { get }
}
class Model {
func report(data: String) {
...
}
}
class Thing: Model, Identifiable {
var id: String
...
}
class Place: Model, Identifiable {
var id: String
...
}
extension (Model + Identifiable) {
func identifiy() {
report("\(self.id)")
}
}
// Invalid: Model().identify()
Place().identify() // OK
Thing().identify() // OK
Extending the protocol itself isn't possible because the extension requires access to methods defined on model
. Extending model fails because the id
is only defined on the child objects. Extending Model: Identifiable
fails because Model
does not conform to protocol Identifiable
.
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.
Swift Class Extensions Another way to add new functionality to a Swift class is to use an extension. Extensions can be used to add features such as methods, initializers, computed properties and subscripts to an existing class without the need to create and reference a subclass.
In Swift, protocols contain multiple abstract members. Classes, structs and enums can conform to multiple protocols and the conformance relationship can be established retroactively.
A Swift extension allows you to add functionality to a type, a class, a struct, an enum, or a protocol.
You could extend Identifiable
, you just need to specify that Self
is a Model
, or subclass of Model
:
extension Identifiable where Self: Model {
func identifiy() {
report(id)
// `id` is already a `String` so there's
// no need to use String Interpolation.
}
}
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