I'm going to explain it by an example. We have a protocol for force having firstName
and lastName
like:
protocol ProfileRepresentable {
var firstName: String { get }
var lastName: String { get }
}
the type we are going to use have these two, but in an optional form:
struct Profile {
var firstName: String?
var lastName: String?
}
so after conforming to the ProfileRepresentable
, we will extend the ProfileRepresentable
and try to return the value and a default one for nil
state:
extension Profile: ProfileRepresentable { }
extension ProfileRepresentable where Self == Profile {
var firstName: String { self.firstName ?? "NoFirstName" }
var lastName: String { self.lastName ?? "NoLastName" }
}
Now there is a similar flow for a list of Profile
s.
protocol ProfilerRepresentable {
var profiles: [ProfileRepresentable] { get }
}
struct Profiler {
var profiles: [Profile]
}
conforming to ProfilerRepresentable
does NOT automatically done the implementation as expected (since Profile
already conforms to ProfileRepresentable
)
extension Profiler: ProfilerRepresentable { }
Following the previous pattern, extending ProfilerRepresentable
is not working as expected and it raises a warning:
⚠️ All paths through this function will call itself
extension ProfilerRepresentable where Self == Profiler {
var profiles: [ProfileRepresentable] { self.profiles }
}
How can I achieve the goal for arrays by the way ?
You can achieve it by mapping the extension's profile result to the needed protocol so that the compiler can understands it:
extension ProfilerRepresentable where Self == Profiler {
var profiles: [ProfileRepresentable] { self.profiles.map { $0 as ProfileRepresentable } }
}