Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift Class Extension Only When Conforming to Protocol

Tags:

ios

swift

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.

like image 546
Kevin Sylvestre Avatar asked Sep 08 '15 00:09

Kevin Sylvestre


People also ask

Can protocols be extended in Swift?

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.

How do you extend a class in Swift?

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.

Can a struct conform to a protocol Swift?

In Swift, protocols contain multiple abstract members. Classes, structs and enums can conform to multiple protocols and the conformance relationship can be established retroactively.

What is the point of extension Swift?

A Swift extension allows you to add functionality to a type, a class, a struct, an enum, or a protocol.


1 Answers

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.
    }
}
like image 141
ABakerSmith Avatar answered Nov 14 '22 04:11

ABakerSmith